/*使用链表实现一个学生信息管理系统。要求:学生有名字(string)、平均成绩(double)、学号(string)三个属性。
实现以下函数:
①、插入一条学生信息,并且保证链表有序,成绩高的靠近链表头。
②、根据名字查询所有同名的学生信息,打印出来
③、实现查询平均成绩在某一区间内的学生个数
④、根据学号删除一条学生信息
⑤、根据学号修改某一个学生的平均成绩,并保持链表有序。(tip:拿出来重新插入一次就可以了))*/
#include <cstdio>
#include <string>
using namespace std;
#define null NULL
struct student{
string name;
double score;
string num;
};
struct node{
node* nxt;
student n;
};
node* createnode()//创建一个结点
{
node* x =null;//初始化NULL或者直接申请内存
x= new node();
x->nxt=null;
return x;
}
void insert(node* head,node* cur)//把结点插入链表
{
node* pre =head;
node* p = head->nxt;
// head-> node1 -> node2 -> node3 -> ...
// pre p
while(p)
{
if(p->n.score < cur->n.score)
{
// ... -> pre -> p -> nodex -> ...
// ...-> pre -> cur -> p -> nodex -> ...
cur->nxt = p;
pre->nxt = cur;
return;
}
pre = p;
p = p->nxt;
}
// p == NULL
// ...->pre -> p(NULL)
pre->nxt =cur;
}
// 错误示范 node* temp;
// if(p==null)
// {
// p=cur;
// cur->nxt=null;
// }
// else
// {
// if((p->n.score)<(cur->n.score))
// {
// // cur-> p
// // head-> p
// cur->nxt=p;
// p=cur;
// }
// else
// {
// while(p!=null&&(p->n.score)>(cur->n.score))
// {
// temp=p;
// p=p->nxt;
// }
// cur->nxt=temp->nxt;
// temp->nxt=cur;
// }
// }
node* querynode(node* head,string name)
{
node* cur=head->nxt;
while(cur)
{
if(cur->n.name==name)
{
return cur;
}
cur=cur->nxt;
}
return null;
}
int queryscope(node* head,double score1,double score2)
{
node* cur=head->nxt;
int n=0;
while(cur)
{
if((cur->n.score)>score1&&(cur->n.score)<score2)
n++;
cur=cur->nxt;
}
return n;
}
void deletenode(node* head,string num)
{
node* pre=head;
node* cur=head->nxt;
while(cur)//遍历
{
if(cur->n.num==num)
{
pre->nxt=cur->nxt;//将cur的后继赋值给pre的后稷
delete cur;//让系统回收此结点,释放内存
break;
}
pre=cur;
cur=cur->nxt;
}
}
node* change(node* head,string num,double gradeavg)
{
node* pre = head;
node* cur=head->nxt;
while(cur)
{
if(cur->n.num==num)
{
// head-> ... -> pre -> cur -> nodex -> ...->
cur->n.score=gradeavg;
pre->nxt=cur->nxt;
// 错误示范 p->n.name=cur->n.name;
// p->n.score=cur->n.score;
// p->n.num=cur->n.num;
// deletenode(head, num);
// head-> ... -> pre -> nodex -> ...->
insert(head,cur);
// head-> ... -> pre -> nodex -> ...-> cur -> ...
return cur;
}
pre = cur;
cur=cur->nxt;
}
return null;
}
void printfNode(node* head)
{
node* temp = head->nxt;
while(temp)
{
printf("%s %lf %s\n",temp->n.name.c_str(),temp->n.score,temp->n.num.c_str());
temp=temp->nxt;
}
}
int main()
{
node* head =createnode();//建一个带头结点的单链表
int a;
printf("输入想要实现的功能:\n1.输入功能\n2.查询功能\n3.查询分数功能\n4.删除功能\n5.修改功能\n");
while(scanf("%d",&a))
{
if(a==1)
{
char name[20],num[20];
double score;
printf("输入学生信息:\n");
scanf("%s%lf%s",name, &score, num);
node* cur=null;
cur=createnode();
cur->n.name=name;
cur->n.score=score;
cur->n.num=num;
insert(head,cur);
}
else if(a==2)
{
char name[20];
printf("输入要查寻的姓名:\n");
scanf("%s",name);
node* que=null;
que=querynode(head,name);
if(que==null)
{
printf("not found\n");
continue;
}
student& v=que->n;
printf("%s%lf%s\n",v.name.c_str(),v.score,v.num.c_str());
}
else if(a==3)
{
double score1,score2;
int m;
printf("输入要查寻的分数区间:\n");
scanf("%lf%lf",&score1,&score2);
m=queryscope(head,score1,score2);
printf("%d\n",m);
}
else if(a==4)
{
char num[20];
printf("输入要删除的学号:\n");
scanf("%s",num);
deletenode(head,num);
}
else if(a==5)
{
char num[20];
double gradeavg;
printf("输入要修改的学号:\n");
scanf("%s%lf",num,&gradeavg);
change(head,num,gradeavg);
}
printfNode(head);
}
}
循环链表:单链表中终端结点的指针端由空指针改为指向头结点
//循环列表的判断方法(追及问题)
#include <cstdio>
#define null NULL;
using namespace std;
struct node
{
node* nxt;
int n;
};
int main()
{
node* head=null;
node* x1=head;
node* x2=head;
while(x1&&x2)
{
x1=x1->nxt;//x1向后移动一次
x2=x2->nxt;
if(x2)
x2=x2->nxt;//x2向后移动两次
else
break;
if(x1==x2)//循环链表就会有x2=x1的时候
{
printf("yes\n");
break;
}
}
}
//错误判断方法,该方法只适用于判断头尾相接的链表
#include <cstdio>
#define null NULL
using namespace std;
struct node{
node* nxt;
int n;
};
int main()
{
node* head=null;
node* cur=head->nxt;
while(cur)
{
cur=cur->nxt;
if(cur==head)
printf("yes\n");
else
break;
}
}