数据结构常用查找排序算法

数据结构常用排序算法(c语言代码)

这是按王卓老师数据结构课的思路实现的排序算法,包括直接插入排序,折半插入排序,希尔排序,冒泡排序,快速排序,简单选择排序,堆排序,归并排序(有bug,有能力的自己修),基数排序,下面将简单的介绍一下每种排序的关键思路:(这里全都假设要把一个序列排位升序)

插入排序:

直接插入排序:

假设前 i-1个元素已经排好,从第i个元素开始向前进行比较,若小于则继续向前比较,若大于第j个元素,则将 j-1到 i-1个元素向后移动一个位置,把第 i 个元素插入到 j+1 位置。

折半插入排序:

与直接插入排序不同的是,查找插入位置时用了折半查找的思路,还是假设从第i个元素开始,设low=1,high=i-1,mid=(low+high)/2,将第i个元素与mid位置的元素进行比较,若小于,则在mid左侧序列再进行折半查找,令high=mid-1;若大于,则在mid右侧序列在进行折半查找,令low=mid+1,直至low=mid为止,最后high+1为要插入位置,对应元素后移,将第 i 个元素插入对应位置

希尔排序:

希尔排序,其实是进行多次直接插入排序,只不过每次向前比较的间隔不一样,直接插入排序的间隔为1,即每次与前一个元素进行比较,希尔排序设置一个dk[ ]数组,用于存放不同的间隔,对每个间隔进行插入排序。

交换排序:

冒泡排序:

从第一个元素开始,两两进行比较,若为逆序则交换位置,若为顺序,则不动,继续比较后一个元素,直到比较到最后一个元素,每一趟比较都把最大的元素放到了数组末尾,所以一共需要比较 序列长度-1 次。

快速排序:

随机选取第 i 元素,设置两个指针low和high分别指向最低元素和最高位置元素,先从高位置像第位置找一个比 i 元素值小的元素,放到最低位置,low++,再从低位置向高位置找一比 i元素值大的元素,放到最高位置,high–,重复上述过程,直至high=low,最后将 i 元素放到low位置处,就是一个升序的序列。

简单选择排序:

顾名思义,想法比较简单,从序列中找到最大的元素,放到序列末尾,在剩余的序列中,重复此操作。

堆排序:

先讲两个概念:大根堆,小根堆

大根堆:即满足以下条件的完全二叉树:每一个非叶子结点都大于他的左右孩子

若有了大根堆后,如何进行排序?先输出根节点,再将剩余的结点在构成一个大根堆,再输出根节点,再构成大根堆,重复上述操作,即能得到一个升序的序列,如何调整剩余结点成大根堆/

堆的调整:将堆顶元素输出后,选取编号最大的元素作为新的根节点,比较左右子树大小,把最大的与其交换,对子树也进行调整,若都比根节点小,则不动。

归并排序:

归并排序先把一个完整的序列拆分成 数量为 序列长度 个 的 元素数量为1的数组,并两个一组进行归并,并构成一组新的排好序的数组,再对新排好序的几组数组,两两进行归并,直至最后归并为一个序列。

基数排序:

又叫桶排序,我们知道可以把一个数字序列分为个、十、百、千、万。。。位,我们把每一个位设置成一个桶,例如有一组无序 数字序列,先将每个数字的个位提取出来,按个位数大小进行排序,再把十位数提取出来,按十位数大小进行排序,直到序列中最高位数排序完毕,得到的序列就为以有序序列。

代码如下

在这里插入代码片
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#define maxsize 100

typedef struct {
	int key;	
}elemtype;

typedef struct{
	elemtype *r;
	int length;
}sqlist;

class sort{
public:
void initsqlist(int n,sqlist &L){	//构造长度为n的队列 
	for(int i=1;i<=n;i++){
		scanf("%d",&L.r[i].key);
	}
	
}

int getlensqlist(sqlist &L){		//返回队列的长度 
	return L.length;
}

void insertsort(sqlist &L){	//插入排序 
	int i,j;
	for(i=2;i<=L.length;i++){		//从第二个元素开始,让他跟前一个元素比较,若小于前一个元素,则应该往前放,若大于则表示他们俩顺序不变 
		if(L.r[i].key<L.r[i-1].key){	//第i个元素大于第i-1个元素时,从第i-1个元素开始向前遍历比较,若比r【i】 大则继续向前,j--,直到找到比他大的元素位置,记录该点位置未j+1 
			L.r[0]=L.r[i];				//先把i-1到j+1间的元素向后移一位,再把r【0】 放入第j位置。 
			for(j=i-1;L.r[j].key>L.r[0].key;j--){	//这里不用考虑j会小于0的情况,因为j=0时,不满足for循环条件,会自动跳出 
				L.r[j+1]=L.r[j];
			}
			L.r[j+1]=L.r[0];
		}
	}
}

void binsertsort(sqlist &L){	//折半排序,与直接插入查找不同的是,在向前找插入位置时,用的是折半查找的方法, 
	int i,j;
	for(i=2;i<=L.length;i++){
		if(L.r[i].key<L.r[i-1].key){
			L.r[0]=L.r[i];
			int low=1,high=i-1;
			while(low<=high){
				int mid=(low+high)/2;
				if(L.r[0].key<L.r[mid].key){
					high=mid-1;
				}
				else{
					low=mid+1;
				}
			}
			for(j=i-1;j>=high+1;j--){
				L.r[j+1]=L.r[j];
			}
			L.r[high+1]=L.r[0];
		}
	}
}

void shellinsert(sqlist &L,int dk){		//希尔排序,其实就是分块的多次直接插入排序,有一个dlta【】数组,保存每次插入排序的间隔,对每个元素进行间隔未dlta【k】 的直接插入排序。 
	int i,j;
	for(i=dk+1;i<=L.length;i++){
		if(L.r[i].key<L.r[i-dk].key){
			L.r[0]=L.r[i];
			for(j=i-dk;j>0 && (L.r[0].key<L.r[j].key);j=j-dk){	//这里向前查找插入位置时,以dk为间隔,当dk=1时,其实就是直接插入排序 
				L.r[j+dk]=L.r[j];
			}
		L.r[j+dk]=L.r[0];
		}
	}
}

void shellsort(sqlist &L,int dlta[],int t) {
	for(int k=0;k<t;k++){
		shellinsert(L,dlta[k]);
	}
}

void Bubble_sort(sqlist &L) {
	int i,j,m;
	for(int m=1;m<L.length;m++){
			for(int j=1;j<=L.length+1;j++){		//向后交换,直到r[j] .key>r[0].key
				if(L.r[j].key>L.r[j+1].key){	//若第i个点大于后面的点 
				L.r[0].key=L.r[j].key;		//暂存到r【0】 
				L.r[j].key =L.r[j+1].key;
				L.r[j+1].key=L.r[0].key;
				}
			//L.r[j-1].key=L.r[0].key;	//
			}
	}
}




int Position(sqlist &L,int low,int high){
	L.r[0]=L.r[low];
	int poskey=L.r[low].key;
	while(low<high){
		while(low<high && L.r[high].key>=poskey) high--;
		L.r[low]=L.r[high];
		while(low < high && L.r[low].key<=poskey) low++;
		L.r[high]=L.r[low];
	}
	L.r[low]=L.r[0];
	return low;		//返回排序完之后的点的位置 
}

void Quick_sort(sqlist &l,int low,int high) {	//随机取一个点,将比它小的放左边,比她大的 放右边,对左右两个集合做同样的操作。 
	if(low<high){								//当low=high时,即low和high相邻时,停止 
	int mid=Position(l,low,high);			// 获取第一个随机点的 位置 
	Quick_sort(l,low,mid-1);				//对该点左边的序列递归调用Quick_sort 
	Quick_sort(l,mid+1,high);				// 对该点右边的序列递归调用Quick_sort 
}
}

void Select_sort(sqlist &l) {	//选择排序,选择最大的插在末尾 
		int max=0;
		int m=l.length;
		for(m;m>=1;m--) {
			int flag=0;
			for(int i=1;i<=m;i++){
				if(l.r[i].key>max){
					max=l.r[i].key;
					flag=i;
				}
			}
			l.r[0]=l.r[flag];	//暂存最大值
			for(flag;flag<=m-1;flag++) {
				l.r[flag]=l.r[flag+1];
			}
			l.r[m]=l.r[0];
		}
}


void HeapAdjust(sqlist &l,int s,int m){		//堆排序,调整 
	int rc=l.r[s].key;	//令rc=s对应的根节点 
	for(int j=2*s;j<m;j*=2){	//从根节点的左孩子开始 
		if(l.r[j].key<l.r[j+1].key) j++;	//找到左右孩子中较大的一个 
		if(rc>l.r[j].key) break;	//若大于r[j] 的值,直接跳出循环
		l.r[s] =l.r[j];	//交换两个元素
		s=j;			//下一次从新位置j开始继续调整,直至交换后的位置为叶子节点 
	}
	l.r[s].key = rc;		//把第一个位置的元素存到确定好的位置 
}

void Heapsort(sqlist &l) {
	int i=0;
	int n=l.length;			//n为l的长度 
	for(i=n/2;i>=1;i--){	// 从n/2开始往前构建堆 
		HeapAdjust(l,i,n);	//构建堆函数 
	}
	for(i=n;i>=1;i--){		//输出根节点 
		printf("%d \t",l.r[1].key);
		l.r[1]=l.r[i];		//把最后一个元素与第一个元素交换。 
		HeapAdjust(l,1,i);		//重调整 
	}
}

/* 
void Merge(int R[],int T[],int low,int mid,int high) { //2路归并 ,比较相邻的两个数组,两个指针分别指向数组头,比较大小 
	int i=low;										   // 小的存到新数组中,将剩余的直接放到末尾。 
	int j=mid+1;
	int k=low;
	while(i<=mid && j<=high){
		if(R[i] < T[i]) T[k++]=R[i++];
		else T[k++]=R[j++];
	}
	while(i<mid) T[k++]=R[i++];
	while(j<high) T[k++]=R[j++];
}

void Merge_sort(int R[],int T[],int low,int high) {	//把给定的序列西安拆分成单个的数组,然后再把相邻的单个数组归并到一起, 
	if(low==high) T[low]=R[low];					// 归并完把数据存入T中,返回上一层递归再归并。。。 
	else{
		int mid=(low+high)/2;
		int S[mid];
		Merge_sort(R,S,low,mid);
		Merge_sort(R,S,mid+1,high);
		Merge(S,T,low,mid,high);		                     
		}
}

void Msort(sqlist &L){
	int n=L.length;
	Merge_sort(L.r,L.r,1,5);
}
*/ 

int Getmaxlen(sqlist L){
	int max=0;
	int n=L.length;
	int flag=0;
	int count=0;
	for(int i=1;i<=n;i++){
		if(max<L.r[i].key) {
			max=L.r[i].key;
			flag=i;
		}
	}
	int maxnum=L.r[flag].key;
	while(maxnum/10 != 0){
		count++;
		maxnum/=10;
	}
	count++;
	return count;
}

void Tone(sqlist &L) {	//桶排序,将数字拆成个、十、百、千。。位,从个位开始对序列重新排序,再从十位开始排序,直到序列数字最大位数排列完
	int n=Getmaxlen(L);	//序列中的最大位数 
	printf("maxlen=:%d\n",n);
	int m=L.length;	 
	int T[m+1];	//T数组存放序列的个位、十位数字。 
	
	for(int j=1;j<=n;j++){	//循环执行 最大位数次 
		for(int i=1;i<=m;i++){	// 
			T[i]=int(L.r[i].key/pow(10,j-1))%10; //从个位开始存进数组中 
			printf("%d\t",T[i]);
		}
		printf("\n");
	for(int k=L.length;k>=1;k--){	//用简单选择排序,把个位的序列从小到大排好,并对原序列做同样的操作。 
		int max=0;
		int flag=1;
		for(int i=k;i>=1;i--){	//这里因为是从小到大排列,在x位值相等的情况下,优先把靠后的值放到末尾,顺序不会出错 
			if(T[i]>max){
				max=T[i];
				flag=i;
			}
		}
		if(max!=0){				//只有当max的值不等于0的时候才将其进行对换,等于0时维持原顺序不动。 
		T[0]=T[flag];
		L.r[0]=L.r[flag];
		for(flag;flag<=k-1;flag++){
			T[flag]=T[flag+1];
			L.r[flag]=L.r[flag+1];
		}
		T[k]=T[0];
		L.r[k]=L.r[0];
	}
	}
}
}
};

int main(){
	sort Sort;
	sqlist L;
	int dlta[5]={5,4,3,2,1};
	L.r=(elemtype*)malloc(sizeof(elemtype)*maxsize);
	printf("请输入顺序表长度:") ;
	scanf("%d",&L.length);
	Sort.initsqlist(L.length,L);
	printf("r[7]=%d\n",L.r[7].key);
	printf("%d\n",Sort.getlensqlist(L));
	Sort.Tone(L);
	//binsertsort(L);
	//shellsort(L,dlta,5);
	//Bubble_sort(L);
	//Quick_sort(L,1,L.length);
	//Select_sort(L);
	//Sort.Select_sort(L);
	//Sort.Heapsort(L);
	//Sort.Merge(L);
	
	for(int i=1;i<=L.length;i++){
		printf("%d\t",L.r[i].key);
	}
	
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值