- 根据下面提供的结构,参照教材“9.5 单链表”中所给出的单链表几种基本操作的代码,完成实现“学生成绩信息”相关的几种功能函数。【此题目为本实验的核心内容】
有一学生成绩表,输入信息包括学号、姓名、3门课程成绩。结构定义如图1所示(可以自行添加别名):
(图1 学生成绩表的结构体定义)
要求实现:
3.1 单链表的创建
函数声明: void CreateStuList( struct stud *head ) ;
说明:创建“学生成绩信息”的单链表,并在创建时完成一些学生结点的构建和链接。
特别说明一下:
在主菜单中,需要嵌入个人信息(如下图所示);
所有的截屏均需要包含个人信息。
输入输出示例,如图2所示:
(图2 创建链表并初始化链表结点)
label at end of compound statement
3.2 单链表的遍历
函数声明: void PrintStuList( struct stud *head ) ;
说明:顺序输出显示单链表中所有结点的信息,每个结点信息占一行。
3.3 单链表的结点插入
函数声明: void StuListInsert( struct stud *head) ;
说明:
(1)若单链表中已存在相同学号的结点,则返回“error!”提示。
(2)在已经有序的“学生成绩信息”单链表中添加新结点,结点插入后,保持链表的有序性。
(3)待插入结点的信息在本函数中接收。
提示:需要从几个方面讨论和考虑问题。输入输出示例,如下面几个图所示:
【情况1】若待添加结点与单链表中已存在学号有重复的,则反馈提示信息,链表中结构不变。如图3所示:
(图3 待添加的结点与链表中信息重复)
【情况2】对链表添加结点。提醒注意,在链表中添加和在链表尾添加,是需要分别对待处理的。如图4和图5所示:
(图4 待添加的结点不在链表尾)
(图5 待添加的结点在链表尾)
3.4 单链表的使用
函数: main()
说明:在理解了单链表各种基本操作的基础上,尝试把这些操作组合到一起,共同实现单链表的应用。对于之前定义的基本操作,在主函数中分别调用,实现单链表的应用。
[拓展]3.5 单链表的结点删除
函数声明: void StuListDelete( struct stud *head )
说明:(1)删除指定学号的链表结点。
(2)若单链表中未找到该学号的结点,则返回“error!”提示。
(3)若找到该学号的结点,则删除该结点。
提示:需要从几个方面讨论和考虑问题。输入输出示例,如下面几个图所示:
【情况1】若链表中确实存在待删除结点,则删除它。提醒注意,结点处于在链表中和链表尾,是需要分别对待处理的。如图6和图7所示:
(图6 待删除的结点在链表尾)
(图7 待删除的结点不在链表尾)
【情况2】若链表中不存在待删除结点,则需要反馈提示信息。如图8所示:
#include <stdlib.h>
#include<string.h>
typedef struct node
{
char id[13];
char name[21];
int score1,score2,score3;
int sum;
struct stud *next;
} Lnode,*LinkList;
int m=sizeof(Lnode);
void CreateStuList(head);
void PrintStuList(head);
void StuListDelete(head);
void ListDelete(LinkList head);
void freelist(LinkList head);
void Statistics(LinkList head);
int main()
{
struct node *head;
int i;
head=(LinkList)malloc(m);
printf("==================================\n");
printf(" **欢迎进入学生信息管理系统*** \n");
printf(" 1:创建链表 \n");
printf(" 2:插入元素 \n");
printf(" 3:删除元素 \n");
printf(" 4:显示元素 \n");
printf(" 5.统计 \n");
printf(" 0:退出系统 \n");
printf("==================================\n");
while(1)
{
printf("请输入菜单项:");
scanf("%d",&i);
switch(i)
{
case 1:
CreateStuList(head);
printf("\n新创建的链表中学生信息为:\n");
PrintStuList(head);
break;
case 2:
printf("当前链表中学生信息为:\n");
PrintStuList(head);
StuListInsert(head);
printf("链表修改后的学生信息:\n");
PrintStuList(head);
break;
case 3:
printf("当前链表中学生信息为:\n");
PrintStuList(head);
ListDelete(head);
printf("链表修改后的学生信息为:\n");
PrintStuList(head);
break;
case 4:
PrintStuList(head);
break;
case 5:
Statistics(head);
break;
case 0:
exit(0);
}
}
freeList(head);
}
void CreateStuList(LinkList head)
{
LinkList s,rear;
head->next=NULL;
rear=head;
int a,b,c;
char e[13];
char r[21];
char w[13]="#";
printf("输入若干整数,输入#表示输入结束\n");
scanf("%s",e);
while(e[0]!='#')
{
getchar();
scanf("%s",r);
scanf("%d",&a);
scanf("%d",&b);
scanf("%d",&c);
if(e[0]!='#')
{
s=(LinkList)malloc(m);//尾插法
strcpy(s->id,e);
strcpy(s->name,r);
s->score1=a;
s->score2=b;
s->score3=c;
s->sum=a+b+c;
s->next=head->next;
rear->next=s;
rear=s;
rear->next=NULL;
scanf("%s",e);
}
}
}
void PrintStuList(LinkList head)
{
LinkList p;
int sum;
p=head->next;
while(p)
{
printf("%s\t%s\t%d\t%d\t%d\t%d\n",p->id,p->name,p->score1,p->score2,p->score3,p->sum);
p=p->next;
}
}
void StuListInsert(LinkList head)
{
LinkList q;
Lnode e;
printf("请输入待添加学生的信息:\n");
scanf("%s %s %d %d %d",e.id,e.name,&e.score1,&e.score2,&e.score3);
printf("\n");
e.sum=e.score1+e.score2+e.score3;
LinkList p;
p=head->next;
int flag;
while(p)
{
if(strcmp(e.id,p->id)==0)
{
flag=1;//有相同的学生
break;
}
if (strcmp(e.id,p->id) < 0)//表头插入
{
flag=2;
break;
}
if(p->next==NULL)
{ flag=3;//从表未插入
break;
}
q=p->next;
if(strcmp(e.id,p->id)>0&&strcmp(e.id,q->id)<0)//表中插
{
LinkList s;
s=(LinkList)malloc(m);
strcpy(s->id,e.id);
strcpy(s->name,e.name);
s->score1=e.score1;
s->score2=e.score2;
s->score3=e.score3;
s->sum=e.score1+e.score2+e.score3;
s->next=p->next;
p->next=s;
break;
}
p=p->next;
}
if (flag==1)
{
printf("学号已有无法添加!\n");
printf("\n");
}
if (flag==2)
{
LinkList s;
s=(LinkList)malloc(m);
strcpy(s->id,e.id);
strcpy(s->name,e.name);
s->score1=e.score1;
s->score2=e.score2;
s->score3=e.score3;
s->sum=e.score1+e.score2+e.score3;
s->next=head->next;
head->next=s;
}
if(flag==3)
{
LinkList s;
s=(LinkList)malloc(m);
strcpy(s->id,e.id);
strcpy(s->name,e.name);
s->score1=e.score1;
s->score2=e.score2;
s->score3=e.score3;
s->sum=e.score1+e.score2+e.score3;
s->next=p->next;
p->next=s;
}
}
void ListDelete(LinkList head)
{
LinkList p,s;
p=head->next;//p为s的上个链表
s=head;
printf("请输入待删除学生的学号信息:\n");
int d=0;
char a[20];
scanf("%s",a);
while(p)
{
if(strcmp(a,p->id)==0)//学号对比
{
printf("待删除学生信息为:\n");
printf("%s %s %d %d %d\n",p->id,p->name,p->score1,p->score2,p->score3,p->sum);
d=1;
break;
}
p=p->next;
s=s->next;
}
if(d==0)
{
printf("ListDelete error\n");
}
else
{
s->next=p->next;//删除
free(p);
}
}
void Statistics(LinkList head)
{
LinkList p;
p=head->next;
int sum,d=0;
printf("成绩不及格的信息统计结果为\n");
while(p)
{
if(p->score1<60||p->score2<60||p->score3<60)
{printf("%s %s %d %d %d\n",p->id,p->name,p->score1,p->score2,p->score3,p->sum);
d=1;
}
p=p->next;
}
if(d==0)
{
printf("无不及格学生\n");
}
}
void freelist(LinkList head)
{
LinkList cur,next;
cur=head->next;
head->next=NULL;
while(cur)
{
next=cur->next;
free(cur);
cur=next;
}
}