C语言实现直接插入、选择、希尔排序

第一篇:

C语言实现成绩的:直接插入排序、选择排序、希尔排序

刚好在学数据结构,想着把自己完成的一些代码发出来,缺陷自然是多多啦,所以希望大家能多多指教!!!
CSDN没用多久,markdown也是第一次用,很蒙圈,本来还想详细解释一下算法什么的,但排版什么的实在是难为我,等什么时候用空再研究研究这些吧!!!

问题描述:
给出n个学生的考试成绩表,每条信息由姓名和分数组成:

  1. 按分数高低次序,打印出每个学生在考试中获得的名次,分数相同的为同一名次;
  2. 按名次列出每个学生的姓名与分数
  3. 给出直接插入排序、选择排序、希尔排序三种排序方式

代码如下

#include <stdio.h>
#include <stdlib.h>

typedef struct Student{
	char name[20];
	int score;
}Student,*ST;

int number = 0;			//学生数量

void shuruxinxi(ST &stu){	
	printf("\n--------------------请输入学生信息------------------");
	for(int k = 0; k < number; k++){
		printf("\n&&第%d位学生\n",k+1);
		printf("姓名:");
		scanf("%s",stu[k].name);
		printf("成绩:");
		scanf("%d",&stu[k].score);
		printf("\n###########################\n");
	}
}

//直接插入排序
ST ChaRuPaiXu(ST stu,int number1){
	ST p = (ST)malloc((number1 + 1)*sizeof(Student));
	for(int m = 1;m<=number1;m++){
		p[m]=stu[m-1];
	}	
	for(int i = 2;i<=number1;i++){
		int kk = i;
		p[0] = p[i];
		for(int j = i-1;p[0].score>p[j].score;j--){
			p[kk] = p[j];
			p[j] = p[0];
			kk = j;
		}
	}	
	return p+1;
}


//选择排序
ST XuanZe(ST stu){
	ST p = (ST)malloc((number)*sizeof(Student));
	ST guoDu = (ST)malloc(sizeof(Student));
	int maxScore;
	for(int m = 0;m<number;m++){
		p[m]=stu[m];
	}
	for(int i = 0;i<number;i++){
		int k = i;
		maxScore = p[i].score;
		for(int j = i+1;j<number;j++){
			if(maxScore < p[j].score){
				maxScore = p[j].score;
				k = j;
			}
		}
		guoDu[0] = p[i];
		p[i]=p[k];
		p[k] = guoDu[0];
	}
	return p;
}

//希尔排序
ST XiErPaiXu(ST stu){
	ST VirtaulStu; 
	ST stu1 = (ST)malloc(number*sizeof(Student));
	for(int num = 0;num<number;num++){
		stu1[num] = stu[num];
	}
	for(int d = number/2;d>=1;d=d/2){
		int n = 0,max;
		n = (number-1)/d;		//n+1后代表一次最多可以读多少个,例如number=8,d=3时一次最多可以从stu[]数组中读3个数:1 4 7或2 5 8
		if(number%(1+n)){		//如果取余之后不等于0代表还需要在多读一次,接上例还有3, 6没读
			max = number/(1+n) + 1;		//max表示到第max个数后+d+d...就能读完,接上例到3可以读完可以分为1 4 7、2 5 8、3 6读完整个数组
		}else {
			max = number/(1+n);	//若取模不等于0意味着每次读n+1个,可以刚好读完整个数组,例如number=8,d=4,则每次读2个,可刚好读完:1 5、2 6、3 7、4 8
		}
		for(int i = 1;i<=max;i++){
			VirtaulStu = (ST)malloc(((number-i)/d + 1)*sizeof(Student));
			for(int j = 0;j<(number-i)/d + 1;j++){
				VirtaulStu[j] = stu1[i-1+d*j];
			}
			VirtaulStu = ChaRuPaiXu(VirtaulStu,((number-i)/d + 1));
			for(int j1 = 0;j1<(number-i)/d + 1;j1++){
				stu1[i-1+d*j1] = VirtaulStu[j1];
			}
		}
	}
	return stu1;
}

//输出排名
void OutPut(ST p){
	int mingci;
	for(int z = 0;z<number;z++){
		if(z == 0 || p[z].score<p[z-1].score){
			mingci = z +1;
		}
		printf("第%d名:姓名:%s\t成绩:%d\n",mingci,p[z].name,p[z].score);
	}
}
//菜单
void meau(){
	printf("\t\t\t&&&&&&&&&&&&&&&&&&&&&&&||学生信息查找||&&&&&&&&&&&&&&&&&&&&&\n");
	printf("\t\t\t&                     A.输入学生数、姓名及成绩             &\n");
	printf("\t\t\t&                     B.用直接插入排序输出名次             &\n");
	printf("\t\t\t&                     C.用选择排序输出名次                 &\n");
	printf("\t\t\t&                     D.用希尔排序输出名次                 &\n");
	printf("\t\t\t&                     E.退出                               &\n");
	printf("\t\t\t&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&\n");
}


void main(){
	ST stu;
	int Assure;
	while(Assure){
		char choose;
		meau();
		printf("请输入选项:");
		scanf("%c",&choose);getchar();
		switch(choose){
		case 'a':
		case 'A':   
			printf("请输入学生总数:\t");
			scanf("%d",&number);
			stu = (ST)malloc(number*sizeof(Student));
			shuruxinxi(stu);
			break;
		case 'b':
		case 'B':	//直接插入排序
			if(number>1){
				OutPut(ChaRuPaiXu(stu,number));
			}else{
				printf("第1名:姓名:%s\t成绩:%d\n",stu[0].name,stu[0].score);
			}
			break;
		case 'c':
		case 'C':	//选择排序
			OutPut(XuanZe(stu));
			break;
		case 'd':
		case 'D':	//希尔排序
			OutPut(XiErPaiXu(stu));
			//XiErPaiXu(stu); 
			break;
		case 'e':
		case 'E':	//退出
			exit(0);			
		default:
			printf("输入错误!!!\n");
		}
		printf("\n是否继续: 是/1 否/0\t");
		scanf("%d",&Assure);
		getchar();			//消除enter符
		printf("\n");
		system("cls");
	}	
}

效果如下:
效果图

直解插入排序

二

选择排序

三

后面的自然也是这样,就不放效果图了,还有一些代码可以简化,一些空间的开辟之类的不太好,之后再改进吧!!!


#THANK YOU观看,欢迎多交流!!!

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值