c语音超详细,用链表建立学生结构体类型,并用数据记录移动法和指针变量交换法排序

问题描述:建立学生结构体类型,包括:学号(学号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;
} 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值