用单链表实现:
学生信息管理系统使用单链表作为基本数据结构,设计一个学生成绩管理系统,用来管理学生的成绩。
功能从0-9选择,根据提示输入相应序号对应实现不同的功能。
完整代码实现:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct student{ //学生信息
char sno[20];//学号
char name[20];//姓名
int chinese;//语文成绩
int math;//数学成绩
int english;//英语成绩
int score;//总分
}stu;
typedef struct Lnode {//链表结点定义
stu data; //数据域
struct Lnode *next;//指针域
}LinkList;
//初始化链表
LinkList *InitList(){
LinkList *head;
head=(LinkList *)malloc(sizeof(LinkList));//动态分配一个结点空间
head->next=NULL;
return head;//头结点L指针为空,表示空链表
}
int LengthList(LinkList *head){//链表长度
LinkList *p=head->next;
int k=0;
while(p!=NULL){
p=p->next;
k++;
}
return k;
}
void menu(){//菜单
printf("\n==================================");
printf("\n\t1.--创建链表");
printf("\n\t2.--显示链表");
printf("\n\t3.--求每门课程的平均分");
printf("\n\t4.--求成绩最大值");
printf("\n\t5.--按学号查找学生");
printf("\n\t6.--按序号位置查找学生");
printf("\n\t7.--按序号删除学生");
printf("\n\t8.--插入学生操作");
printf("\n\t9.--对学生按分数进行排序");
printf("\n\t0.--返回");
printf("\n==================================");
printf("\n==请输入==");
printf("\n请输入选择项:\n");
}
//1.创建链表
void CreateListL(LinkList *head,int n){//尾插法建表
LinkList *s,*last;
int i;
last=head; //last始终指向尾结点,开始时指向头结点
for(i=0;i<n;i++){
s=(LinkList *)malloc(sizeof(LinkList));//生成新节点
printf("请输入第%d个同学的学号,姓名,数学成绩,语文成绩,英语成绩:",i+1);//创建提示
scanf("%s%s%d%d%d",&s->data.sno,&s->data.name,&s->data.math,&s->data.chinese,&s->data.english);//读入新结点数据域
s->next=NULL; //新结点指针域为空
last->next=s; //新结点插入表尾
last=s; //last指针指向表尾结点
}
printf("\n建立链表操作成功!\n");
}
//2.显示链表
void DispList(LinkList *head){
LinkList *p;
p=head->next;
printf("id\tname\tMath\tChinese\tEnglish\tscore\n");
while(p!=NULL){
p->data.score=p->data.math+p->data.chinese+p->data.english; //求各成绩总分score
printf("%s\t%s\t%d\t%d\t%d\t%d\n",p->data.sno,p->data.name,p->data.math,p->data.chinese,p->data.english,p->data.score);//打印输出各项信息
p=p->next;
}
}
//3.每门课程平均分
void AveGrade(LinkList *head){
LinkList *p;
p=head->next;
int y=LengthList(head);
printf("共有%d个学生信息\n",y);//后面插入及删除学生,学生人数会变化,便于计算平均分
double aveMath,aveChinese,aveEnglish;//每门平均成绩
double SumEnglish,SumMath,SumChinese;//每门成绩之和
while(p!=NULL){
SumMath+=p->data.math; //各成绩求和
SumChinese+=p->data.chinese;
SumEnglish+=p->data.english;
p=p->next;
}
aveMath=SumMath/y;
aveChinese=SumChinese/y;
aveEnglish=SumEnglish/y;
printf("各门课程的平均分如下:\n");
printf("aveMath=%0.4f \t aveChinese=%0.4f \t aveEnglish=%0.4f",aveMath,aveChinese,aveEnglish);//打印输出平均分保留四位小数
}
//4.求成绩最大值
void MaxGrade(LinkList *head){
LinkList *p;
int i=1,k,MAX;
p=head->next;
while(p!=NULL){
if(p->data.score>MAX){//找出最大score
MAX=p->data.score;
k=i;//记录位置
}else{
MAX=MAX;
}
// printf("%d ",p->data.score); //score
p=p->next;
i++;
}
printf("\n成绩最大值的位置:%d,成绩为:%d \n",k,MAX);
}
//5.按学号查找学生
void SnoLocate(LinkList *head, char *str){
int flag=1;//记录位置
LinkList *p;
p=head->next;
while(p!=NULL){
if(strcmp(p->data.sno,str)==0){ //字符串进行比较 相等找到学号并输出信息,没有找到返回主菜单
printf("在表的第%d个位置上找到该学生,学号:%s,姓名:%s\n",flag,p->data.sno,p->data.name);
}
p=p->next;
flag++;
}
}
//6.按序号位置查找学生
void SearchList(LinkList *head,int i){
LinkList *p;
int j=0;
p=head;//p指向链表的头结点
if(i>LengthList(head))
printf("位置错误,链表中没有找到该位置!\n");
while(p->next!=NULL && j<i){
p=p->next;
j++;
}
if(j==i){ //判断与输入的序号位置是否相等
printf("在第%d位置上找到学生,学号为:%s 姓名为:%s",i,p->data.sno,p->data.name);
}
}
//7.按序号删除操作
void DelList(LinkList *head,int i){
int j=0;
stu x;
LinkList *p=head,*s;
while(p->next!=NULL && j<i-1){//定位插入点
p=p->next;
j++;
}
if(p->next!=NULL && j==i-1){
s=p->next;
x=s->data;//将要删除的数据放入指针变量x中
p->next=s->next;//将p结点的指针域与q结点后面元素相连
free(s);
// printf("删除学生后的链表内容如下:\n");
// DispList(head);
} else{
printf("删除失败!\n");
}
}
//8.插入学生操作
void InsList(LinkList *head,int i,stu x){
int j=0;
LinkList *p,*s;
p=head;
while(p->next!=NULL && j<i-1){//定位插入位置,找到第i-1个结点
p=p->next;
j++;
}
if(p!=NULL){
s=(LinkList *)malloc(sizeof(LinkList));//申请新的结点空间s
s->data=x;//将数据x放入新结点的数据域中
s->next=p->next;//将新结点s的指针域与p结点后面元素相连
p->next=s;//将p与新结点s连接
printf("插入成功!\n");
}
}
//9降序score排序
void find(stu *data,LinkList *head){
int i=1; //用i来记录最高结点位置
LinkList *p = head;
p = head->next;
*data = p->data;
while (p->next!=NULL) {
p = p->next;
if (p->data.score > data->score) {
*data = p->data;
i++;
}
}
// data->score=data->math+data->chinese+data->english; //总分score
// printf("%s\t%s\t%d\t%d\t%d\t%d\n",data->sno,data->name,data->math,data->chinese,data->english,data->score);//打印输出score最大的那一行信息
// printf("位置:%d",i); //最大分数的位置
DelList(head,i);//按最大score信息并从A表删除,调用删除函数
}
void buildlistB(LinkList *B,LinkList *head,stu *data,int n){ //用尾插法创建链表B
LinkList *s,*last;
last=B;
for(int j=0;j<n;j++){
s=(LinkList *)malloc(sizeof(LinkList));//生成新节点
find(data,head); //调用 找出score最大函数
s->data=*data; //将最大score依次存入
s->next=NULL; //新结点指针域为空
last->next=s; //新结点插入表尾
last=s; //last指针指向表尾结点
}
printf("\n建立链表操作成功!\n");
}
int main(){
int i,n;
char str[20];
stu x;
stu L;
LinkList *head,*p;
char ch1,ch2,a;
ch1='Y';
while(ch1=='Y' || ch2=='y'){
menu();
scanf("%c",&ch2);
getchar();
switch(ch2){
case '1':
head=InitList();
printf("初始化完成!\n");
printf("请输入学生人数:\n");
scanf("%d",&n);
CreateListL(head,n);
break;
case '2':
DispList(head);
break;
case '3':
AveGrade(head);
break;
case '4':
MaxGrade(head);
break;
case '5':
printf("请输入查找的学号:");
scanf("%s",&str);
SnoLocate(head,str);
break;
case '6':
printf("请输入要查找学生的位置:\n");
scanf("%d",&i);
SearchList(head,i);
break;
case '7':
printf("请输入要删除学生的位置:\n");
scanf("%d",&i);
DelList(head,i);
printf("删除成功!\n");
break;
case '8':
label:
printf("请输入要插入学生的位置:\n");
scanf("%d",&i);
getchar();
if(i>LengthList(head)+1){
printf("插入错误,请重新插入!\n");
goto label;
}
printf("请输入要插入同学的 学号,姓名,数学成绩,语文成绩,英语成绩:");
scanf("%s%s%d%d%d",&x.sno,&x.name,&x.math,&x.chinese,&x.english);
InsList(head,i,x);
break;
case '9':
LinkList *B;
B=InitList(); //B表初始化
printf("初始化完成!\n");
int m;
m=LengthList(head);
buildlistB(B,head,&L,m); //链表B建立函数
printf("A链表为空:\n");
DispList(head); //显示链表A内容:为空
printf("\nB链表进行降序排序:\n");
DispList(B); //显示链表B内容(降序)
break;
case '0':
ch1='n';
break;
default:
printf("输入有误!,请重新输入(0-9)!\n");
}
if(ch2!='0'){
printf("\n按回车键继续,按任意键返回主菜单\n");
a=getchar();
if(a!='\xA'){
getchar();ch1='n';
}
}
}
}
示例运行截图: