双链表嵌套实现简单学生成绩管理系统
(师承上官可编程)
场景:一个年级,相当于链表A,该年级5个班,每个班5个人,相当于链表B1–B5。功能:录入学生基本信息和成绩,找出最高分、最低分、平均分。
全代码展示
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct Class //班级结构体
{
char *Class;
struct Class *next;
struct Student *Stuhead;
};
struct Student //学生结构体
{
char *Name;
int Chinese;
int Math;
int English;
int Sum;
struct Student *next;
};
struct Class *Chead = NULL;
struct Student *Shead = NULL;
void PrintClassStudent() //输出所有学生的信息
{
struct Class *p1;
p1 = Chead;
struct Student *p2 = NULL;
while (p1 != NULL)
{
p2 = p1->Stuhead;
while (p2 != NULL)
{
printf("%s\n", p1->Class);
printf("%s的%s\n", p1->Class, p2->Name);
printf("%s的%s语文成绩为:%d\n", p1->Class, p2->Name, p2->Chinese);
printf("%s的%s数学成绩为:%d\n", p1->Class, p2->Name, p2->Math);
printf("%s的%s英语成绩为:%d\n", p1->Class, p2->Name, p2->English);
printf("%s的%s三科总成绩为:%d\n", p1->Class, p2->Name, p2->Sum);
p2 = p2->next;
}
p1 = p1->next;
}
}
struct Student *AddStudentNode(struct Student *Shead, struct Student *new)
{
struct Student *p; //尾插法创建学生链表
p = Shead;
if (Shead == NULL)
{
Shead = new;
return Shead;
}
while (p->next != NULL)
{
p = p->next;
}
p->next = new;
return Shead;
}
struct Student *ScanfStudent(struct Student *Shead) //输入学生信息
{
struct Student *p;
p = Shead;
int i;
for (i = 0; i < 5; i++)
{
struct Student *new = (struct Student *)malloc(sizeof(struct Student));
new->Name = (char *)malloc(sizeof(char));
new->next = NULL;
printf("请输入学生姓名\n");
scanf("%s", new->Name);
printf("请输入学生语文成绩\n");
scanf("%d", &(new->Chinese));
printf("请输入学生数学成绩\n");
scanf("%d", &(new->Math));
printf("请输入学生英语成绩\n");
scanf("%d", &(new->English));
new->Sum = new->Chinese + new->Math + new->English;
p = AddStudentNode(p, new);
}
return p;
}
struct Class *AddClassNode(struct Class *Chead, struct Class *new)//尾插法创建班级链表
{
struct Class *p;
p = Chead;
if (Chead == NULL)
{
Chead = new;
return Chead;
}
while (p->next != NULL)
{
p = p->next;
}
p->next = new;
return Chead;
}
struct Class *ScanfClass(struct Class *Chead) //输入班级信息
{
struct Class *p;
struct Class *new;
p = Chead;
new = (struct Class *)malloc(sizeof(struct Class));
new->Class = (char *)malloc(sizeof(char));
new->next = NULL;
new->Stuhead = NULL;
printf("请输入班级\n");
scanf("%s", new->Class);
new->Stuhead = ScanfStudent(Shead);
p = AddClassNode(p,new);
return p;
}
struct Class* AllNode() //连接班级链表
{
int i;
for (i = 0; i < 5; i++)
{
Chead = ScanfClass(Chead);
}
return Chead;
}
int SumMax(struct Class *Chead) //获取学生的最高分
{
int mark = 0;
struct Class *p1;
p1 = Chead;
struct Student *p2 = NULL;
mark = p1->Stuhead->Sum;
while (p1 != NULL)
{
p2 = p1->Stuhead;
while (p2 != NULL)
{
if (p2->Sum > mark)
{
mark = p2->Sum;
}
p2 = p2->next;
}
p1 = p1->next;
}
return mark;
}
int SumMin(struct Class *Chead) //获取学生的最低分
{
int mark = 0;
struct Class *p1;
p1 = Chead;
struct Student *p2 = NULL;
mark = p1->Stuhead->Sum;
while (p1 != NULL)
{
p2 = p1->Stuhead;
while (p2 != NULL)
{
if (p2->Sum < mark)
{
mark = p2->Sum;
}
p2 = p2->next;
}
p1 = p1->next;
}
return mark;
}
float Average(struct Class *Chead) //获取学生的平均分
{
float mark = 0;
struct Class *p1;
p1 = Chead;
struct Student *p2 = NULL;
while (p1 != NULL)
{
p2 = p1->Stuhead;
while (p2 != NULL)
{
mark = mark + p2->Sum;
p2 = p2->next;
}
p1 = p1->next;
}
return mark/25;
}
int main()
{
Chead = AllNode();
printf("-----------------------------\n");
PrintClassStudent();
printf("-----------------------------\n");
printf("全年级最高分为:%d\n",SumMax(Chead));
printf("-----------------------------\n");
printf("全年级最低分为:%d\n",SumMin(Chead));
printf("-----------------------------\n");
printf("平均分为:%f\n",Average(Chead));
system("pause");
return 0;
}
要点(链表的动态创建)
个人见解:链表的创建有头插法和尾插法,我用的是尾插法创建学生和班级链表,核心:一开始输入数据时,头节点都为空,这就需要判断,如果头节点为空的话,让头节点等于新创建的节点即可,切记要return head;不然就会出现段错误。当插入第二个节点时,头节点不为空,就需要(使用while循环)找到最后一个节点,让p->next = new 即可。
注意:不能轻易改头节点,不然指针会跑飞。
总结
个人见解:这个系统是一个双链表系统,母链表的每一个节点包含一个子链表的头节点,可以根据这个思想来创建和遍历链表,核心就是建立好这个双链表,其他的可以根据遍历链表来找出最高分、最低分、平均分。如图: