问题描述:建立学生结构体类型,包括:学号(学号11位)、姓名、3门课成绩及总分。采用链表来存放学生信息,从键盘录入10个同学的信息(总分自动计算不录入),采用头插法建立学生链表。然后对这10个同学按总分从低到高的顺序排序(即排序后链表的第一个结点存放总分最低的学生信息,每二个结点存放总分次低的学生信息,……),然后在屏幕上输出排序后的所有学生记录,并将排序好的链表写入文件中。假设本问题中,学生3门课成绩一定为[0,100]之间的正整数。要求使用冒泡排序法来完成本实验。要求采用两种方法来实现排序,即数据记录移动法和指针变量交换法。
//建立建立学生结构体类型,链表排序
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define N 10
#define LEN sizeof(struct student)
struct student //创建学生结构体
{
char num[12];
char name[20];
int score[3];
int sum;
struct student *next;
};
struct student *creat();//创链表,用函数返回头结点地址
int sort(struct student *head);//数据交换法
//int sort1(struct student *head);//指针交换法 无法为头结点排序,两个节点无法排序.....
int main()
{
struct student *head=NULL,*p3,*p,stu[20];
char s[12],*max_name;
head=creat();
sort(head);
//sort1(head);
p3=head;
while(p3->next!=NULL)//输出测试
{
printf("学生 %s 3门课的总成绩:%d\n",p3->num ,p3->sum);
p3=p3->next;
}
FILE* pf=fopen("E:\\student.txt","w");//将数据传入文件
if(pf==NULL)
return 0;
fwrite(stu,1,sizeof(struct student),pf);
fclose(pf);
free(p);
return 0;
}
struct student *creat()//创建链表
{
struct student *head,*p;//头插法
//struct student *p1,*p2;//处理指针
int i,j,n=0;
//p1=p2=(struct student *)malloc(LEN);//开辟新单元
head=(struct student *)malloc(LEN);
head->next=0;
printf("请输入学号姓名和成绩\n");
while(n<N)
{
/*p1->sum=0;
scanf("%s %s ",&p1->num,&p1->name);//依次输入学生学号姓名
for(j=0;j<3;j++)
{
scanf("%d",&p1->score[j]);
p1->sum+=p1->score[j];//计算总成绩
}
if(n==0)
head=p1;
else
p2->next=p1;
p2=p1;//将p1数据放到p2中
p1=(struct student *)malloc(LEN);
n++;
}
p2->next=NULL; 双指针创链表*/
p=(struct student*)malloc(LEN);//新申请下一个插入节点
p->sum=0;
scanf("%s%s",&p->num,&p->name);//依次输入学生学号姓名
for(j=0;j<3;j++)
{
scanf("%d",&p->score[j]);
p->sum+=p->score[j];//计算总成绩
}
p->next=head->next;//当前新节点插在第一个(头插法),即新节点指向原头结点指向的结点
head->next=p;//新节点插在第一个(头插法),head的指针域指向它
n++;
}
return head;
}
/*按照平均分排序-冒泡法排序-降序
链表冒泡排序思想:设置两个指针,一个是当前指针,一个是尾指针,当前的指针指向头节点,将尾指针赋为空,
当当前的指针不等于尾指针是一次循环,第一次将当前一个节点的值与下一个节点的值相比较,直到下一个节点和尾指针相等(即为空),
结束本次循环,最后当前的指针赋给尾指针,当前指针重新指向头结点,再两两相比较,把最大(或最小)的数放在最后
*/
int sort(struct student *head)//数据交换法
{
struct student *p,*tail;
p=head;
tail=NULL;
if(p==NULL||p->next==NULL)return 0;//空链表
while(p!=tail)//循环到表尾 即原来的for(i=0;i<LEN-1;i++)
{
while(p->next!=tail)//循环到最后剩一个 j<LEN-1-i
{
if(p->sum>p->next->sum)//两两比较,数据交换
{
int temp=p->sum;
p->sum=p->next->sum;
p->next->sum=temp;
int temp1=p->score[0];
p->score[0]=p->next->score[0];
p->next->score[0]=temp1;
temp1=p->score[1];
p->score[1]=p->next->score[1];
p->next->score[1]=temp1;
temp1=p->score[2];
p->score[2]=p->next->score[2];
p->next->score[2]=temp1;
char tc[20],*temp2=tc;
strcpy(temp2,p->num);
strcpy(p->num,p->next->num);
strcpy(p->next->num,temp2);
strcpy(temp2,p->name);
strcpy(p->name,p->next->name);
strcpy(p->next->name,temp2);
}
p=p->next;//循环下一次
}
tail=p; //表尾更新,排序链表少1个元素了,即内循环条件(p->next!=tail)不满足是tail的上一个节点(该节点指针与中放的是tail节点)
p=head;
}
return 0;
}
int sort1(struct student *head)//指针交换法
{
struct student *p,*q,*tail;
if(head->next==NULL) return; //空链表
tail = NULL;
while((head->next) != tail) //循环到表尾 即原来for (i=0;i<len-1;i++)
{
p = head; //当前节点的前一个节点
q = head->next; //当前节点
while(q->next != tail) //循环到最后剩1个,即原来 j<len-1-i
{
if((q->sum) > (q->next->sum)) //两两比较 就是 a[j]与a[j+1]比较
{
p->next = q->next; //当前节点前一个节点指向当前节点后一个节点
q->next = q->next->next; //当前节点指向当前节点后一个节点的后面
p->next->next = q; //当前节点后一个节点指向当前节点
q = p->next; //交换完毕后,当前节点向后移动一个节点
}
q = q->next; //当前节点后移,循环下一次 均是原来for 循环的 j=j+1
p = p->next; //当前节点前一个节点后移,
}
tail = q; //表尾更新,排序链表少1个元素了,即内循环条件(p->next!=tail)不满足是tail的上一个节点(该节点指针与中放的是tail节点)
}
return 0;
}