#include <stdio.h> #include <stdlib.h> #include<string.h> #define N 100 void tillinsert(int id,char *name,float score);//尾部插入结点 void print();//输出链表全部信息 void headinsert(int id,char *name,float score);//头部插入结点 void nodeinsert(int id,char *name,float score,int idtemp);//从一个结点前插入 void deletenode(int id);//删除结点 void deletehead();//删除头结点 void deletetill(); //删除尾结点 //创建结构体 struct student{ int id; char name[N]; float score; struct student* next; }; //初始化头尾结点 struct student* head=NULL; struct student* end=NULL; //主函数 int main(){ int id; char name[N]; float score; int m; printf("1.输入1,输入学生信息。\n2.输入2,从尾部插入一个节点。\n3.输入3,从头部插入一个结点。\n4.输入4,从一个指定结点前插入一个结点。\n5.输入5,删除一个指定结点。\n6.输入6,显示当前链表信息。\n7.输入7,退出程序。\n"); while(m!=7){ scanf("%d",&m); if(m==1){ printf("请输入学生总数:\n"); int i,n; scanf("%d",&n); printf("请按顺序输入学生的id,姓名,分数,中间空格隔开\n"); for(i=1;i<=n;i++){ scanf("%d",&id); scanf("%s",name); scanf("%f",&score); tillinsert(id,name,score); } } if(m==2){ printf("从头部插入结点,请输入数据:\n"); scanf("%d",&id); scanf("%s",name); scanf("%f",&score); headinsert(id,name,score); } if(m==3){ printf("从尾部插入结点,请输入数据:\n"); scanf("%d",&id); scanf("%s",name); scanf("%f",&score); tillinsert(id,name,score); } if(m==4){ printf("从任意一个前插入新的结点,请输入该结点中id:\n"); int idtemp; scanf("%d",&idtemp); printf("请输入要插入结点中的数据:\n"); scanf("%d",&id); scanf("%s",name); scanf("%f",&score); nodeinsert(id,name,score,idtemp); } if(m==5){ printf("请输入所要删除的结点的id:\n"); scanf("%d",&id); deletenode(id); } if(m==6){ print(); } if(m!=7){ printf("程序运行完毕,请进行下一步操作:\n");} } return 0; } //从尾部插入结点 void tillinsert(int id,char *name,float score){ //创建结点 开辟空间 struct student* p1=(struct student*)malloc(sizeof(struct student)); //参量赋值 //由于字符数组的特殊性,采用strcpy函数来赋值 p1->id=id; strcpy(p1->name,name); p1->score=score; p1->next=NULL; if(head==NULL||end==NULL){ head=p1; end=p1; } else{ end->next=p1; end=p1; } } //输出链表信息 void print(){ struct student* p=head; printf("该链表的信息目前为:\n"); while(p!=NULL){ printf("id:%d name:%s score:%f\n",p->id,p->name,p->score); p=p->next; } } //头部插入结点 void headinsert(int id,char *name,float score){ struct student* p2=(struct student*)malloc(sizeof(struct student)); p2->id=id; strcpy(p2->name,name); p2->score=score; if(head==NULL||end==NULL){ head=p2; end=p2; } else{ p2->next=head; head=p2; } } //从一个结点前插入新的结点 idtemp为所要插入的结点对应的id void nodeinsert(int id,char *name,float score,int idtemp){ struct student* p3=head; //特殊情况:对应id为头结点的id,即刚好要插入头结点前 if(p3->id==idtemp){ headinsert(id,name,score); return; } //非特殊情况:先遍历查找指定位置 while(p3->next!=NULL){ if(p3->next->id==idtemp){ break; } p3=p3->next; } //如若没有查找到指定结点 if(p3->next==NULL){ printf("该结点不存在\n"); return; } //已经查找到指定结点,建立要插入的结点并赋值 struct student* ptemp=(struct student*)malloc(sizeof(struct student)); ptemp->id=id; strcpy(ptemp->name,name); ptemp->score=score; //连接结点 ptemp->next=p3->next; p3->next=ptemp; } void deletehead(){//定义函数删除头结点,主要为后续删除结点做准备 struct student* ptemp=head; head=head->next; free(ptemp); } void deletetill(){//删除尾结点,为后续删除结点做准备 //第一种情况下,只有一个结点 if(head==end){ free(head); head=NULL; end=NULL; } else{ //找到尾巴前一个结点 struct student* ptemp=head;//ptemp为尾巴前面的一个结点 struct student* pt=end;//pt为尾结点 while(ptemp->next!=end){ ptemp=ptemp->next; } end=ptemp;//尾巴前移 free(pt);//释放旧的尾结点 end->next=NULL; } } //删除结点 void deletenode(int id){ //如果链表为空 if(head==NULL){ printf("该链表为空\n"); return; } //查询是否有该结点 struct student* p=head; while(p!=NULL){ if(p->id==id){ break; } p=p->next; } if(p==NULL){ printf("未找到此结点\n"); return; } //判断特殊情况, 即p是否为头尾结点中的一个 else if(p==head){ deletehead(); } else if(p==end){ deletetill(); } else{ //非特殊情况,需要找到所删除结点的前一个结点 struct student* ptemp=head; while(ptemp->next!=p){ ptemp=ptemp->next; } ptemp->next=p->next; free(p); } }