六大排序

1.插入排序

1.1直接插入排序

/*直接插入排序是插入排序中最简单的排序方法,类似于玩纸牌时整理手中纸牌
的顺序。基本思想就是:依次将待排序中的每一个记录插入到一个已经排序好的序列中
知道所有序列都排好序 
*/

void Insert_sort(int a[],int n){
	for(int i=1;i<n;i++){
		int temp=a[i];//先保存当前位置的元素
		int k;
		for(k=i-1;k>=0&&a[k]>temp;k--){//将比temp值都大的元素往后咦,给temp让位 
			a[k+1]=a[k];
		} //循环结束后,k在指定位置的前一个位置 
		a[k+1]=temp;
	} 
} 

1.2希尔排序

/*希尔排序
希尔排序是对直接插入排序的一种改进,改进的着眼点在于
①若待排序的记录按关键码基本有序,直接插入排序的效率很高
②由于直接插入排序算法简单,则在待排序记录个数较少的时候效率也很高
希尔排序的基本思想是:
先将整个待排序记录序列分割成若干个子序列,在子序列内分别进行直接插入排序,
待整个序列基本有序时,再对全体记录进行一次直接插入排序*/

void Shell_sort(int a[],int n){
	for(int d=n/2;d>=1;d/=2){
		//直接插入排序只不过是d=1的情况,因此下面只需要在直插的基础上,加d就好啦
		for(int i=d+1;i<n;i++){
			int temp=a[i];
			int k;
			for(k=i-d;k>=0&&a[k]>temp;k-=d){
				a[k+d]=a[k];
			}
			a[k+d]=temp;
		} 
	}
} 

2.交换排序

2.1冒泡排序

/*冒泡排序
冒泡排序是交换排序中最简单的排序方法,基本思想是:
两两比较相邻记录的关键码,如果反序则交换,直到没有反序记录位置*/

void Bubble_sort(int a[],int n){
	for(int k=n-1;k>0;k--){//从小到大排序 
		int flag=1;//用于记录有没有进行过交换
		for(int i=0;i<k;i++){
			if(a[i]>a[i+1]){//记录反序 
				swap(a[i],a[i+1]);
				flag=0;//这一趟排序中,进行了交换 
			}
		} 
		if(flag){
			break;//一趟排序中,未进行过交换,则已经有序了,退出 
		}
	}
}

2.2快速排序

/*快速排序
快速排序又称为分区域交换排序,基本思想是:
首先选择一个轴值,将待排序的记录分成独立的两个部分
左侧记录均小于或等于轴值,右侧记录的关键码均大于或等于轴值
然后分别对着两部分重复上述的过程,直到整个序列有序 
*/

int partition(int a[],int first,int end){
	int x=a[first];//进行保存 
	int i=first,j=end;
	while(i<j){
		while(i<j&&a[j]>=x){
			j--;//从后往前扫描,j指向第一个小于x的值 
		}
		if(i<j){
			a[i]=a[j];//把比x小的放到左边
		}
		while(i<j&&a[i]<=x){
			i++;//i从前往后扫描,i指向第一个比x大的值 
		}
		if(i<j){
			a[j]=a[i];//把比x大的值放到右边 
		}
	}
	a[i]=x;
	return i; 
} 
void Qsort(int a[],int first,int end){
	int p;
	if(first<end){
		p=partition(a,first,end);//确定轴
		Qsort(a,first,p-1);//分治进行排序 
		Qsort(a,p+1,end); 
	}
}
//为了和其他排序的接口相同,加了上面的辅助函数 
void Quick_sort(int a[],int n){
	Qsort(a,0,n-1);
}

3.选择排序

3.1简单选择排序

/*简单选择排序
简单选择排序是选择排序中最简单的排序方法
其基本思想是,第i趟排序在待排序区间r[i]~r[n]
中选取关键码最小的记录,并和第i个记录交换
作为有序序列的第i个记录*/

void Select_sort(int a[],int n){
	for(int i=0;i<n;i++){
		int k=i;
		for(int j=i+1;j<n;j++){//无序区选择一个最小的 
			if(a[j]<a[k]){
				k=j;//标记最小的那个下标 
			}
		}
		if(k!=i){
			swap(a[i],a[k]);
		} 
	}
} 

3.2堆排序

/*堆排序
堆排序是简单选择排序的一种改进,
改进的着眼点在于,如何减少关键码的比较次数
简单选择排序实在一趟排序中仅选出最小关键码,没有把一趟比较结果保存下来*/

void shift(int a[],int k,int m){//n-1
	//k为根的编号,m为最后一个叶子的编号
	int i=k;
	int j=i*2+1;//左孩子 
	int x=a[i];//保存好当前元素
	while(j<=m){
		if(j<m&&a[j]<a[j+1]){
			j++;//j指向较大的那个 
		}
		if(x>a[j]){//已经比较大的大,则已经成为了较大堆 
			break;
		}else{
			a[i]=a[j];
			i=j;
			j=i*2+1; 
		} 
	} 
	a[i]=x; 
} 
//堆排序,下标从1开始 
void Heap_sort(int a[],int n){
	for(int i=n/2;i>=0;i--){//初始建堆,从最后一个分支,一直到根节点 
		shift(a,i,n-1);
	}
	for(int i=n-1;i>=1;i--){
		swap(a[i],a[0]);//把最大的节点a[1]放到最后面
		shift(a,0,i-1);//只有第一个顶点不一定满足大根堆 
	} 
}

把所以的代码贴在下面

#include <iostream>
using namespace std;

void Insert_sort(int a[],int n);//直接插入排序
void Shell_sort(int a[],int n);//希尔排序
void Bubble_sort(int a[],int n);//冒泡排序 
void Quick_sort(int a[],int n);//快速排序 
void Select_sort(int a[],int n);//选择排序
void  Heap_sort(int a[],int n);//堆排序 
void show(int a[],int n);//显示 
/*直接插入排序是插入排序中最简单的排序方法,类似于玩纸牌时整理手中纸牌
的顺序。基本思想就是:依次将待排序中的每一个记录插入到一个已经排序好的序列中
知道所有序列都排好序 
*/
void Insert_sort(int a[],int n){
	for(int i=1;i<n;i++){
		int temp=a[i];//先保存当前位置的元素
		int k;
		for(k=i-1;k>=0&&a[k]>temp;k--){//将比temp值都大的元素往后咦,给temp让位 
			a[k+1]=a[k];
		} //循环结束后,k在指定位置的前一个位置 
		a[k+1]=temp;
	} 
} 
/*希尔排序
希尔排序是对直接插入排序的一种改进,改进的着眼点在于
①若待排序的记录按关键码基本有序,直接插入排序的效率很高
②由于直接插入排序算法简单,则在待排序记录个数较少的时候效率也很高
希尔排序的基本思想是:
先将整个待排序记录序列分割成若干个子序列,在子序列内分别进行直接插入排序,
待整个序列基本有序时,再对全体记录进行一次直接插入排序*/
void Shell_sort(int a[],int n){
	for(int d=n/2;d>=1;d/=2){
		//直接插入排序只不过是d=1的情况,因此下面只需要在直插的基础上,加d就好啦
		for(int i=d+1;i<n;i++){
			int temp=a[i];
			int k;
			for(k=i-d;k>=0&&a[k]>temp;k-=d){
				a[k+d]=a[k];
			}
			a[k+d]=temp;
		} 
	}
} 
/*冒泡排序
冒泡排序是交换排序中最简单的排序方法,基本思想是:
两两比较相邻记录的关键码,如果反序则交换,直到没有反序记录位置*/
void Bubble_sort(int a[],int n){
	for(int k=n-1;k>0;k--){//从小到大排序 
		int flag=1;//用于记录有没有进行过交换
		for(int i=0;i<k;i++){
			if(a[i]>a[i+1]){//记录反序 
				swap(a[i],a[i+1]);
				flag=0;//这一趟排序中,进行了交换 
			}
		} 
		if(flag){
			break;//一趟排序中,未进行过交换,则已经有序了,退出 
		}
	}
} 
/*快速排序
快速排序又称为分区域交换排序,基本思想是:
首先选择一个轴值,将待排序的记录分成独立的两个部分
左侧记录均小于或等于轴值,右侧记录的关键码均大于或等于轴值
然后分别对着两部分重复上述的过程,直到整个序列有序 
*/
//辅助函数,进行区域的划分 
int partition(int a[],int first,int end){
	int x=a[first];//进行保存 
	int i=first,j=end;
	while(i<j){
		while(i<j&&a[j]>=x){
			j--;//从后往前扫描,j指向第一个小于x的值 
		}
		if(i<j){
			a[i]=a[j];//把比x小的放到左边
		}
		while(i<j&&a[i]<=x){
			i++;//i从前往后扫描,i指向第一个比x大的值 
		}
		if(i<j){
			a[j]=a[i];//把比x大的值放到右边 
		}
	}
	a[i]=x;
	return i; 
} 
void Qsort(int a[],int first,int end){
	int p;
	if(first<end){
		p=partition(a,first,end);//确定轴
		Qsort(a,first,p-1);//分治进行排序 
		Qsort(a,p+1,end); 
	}
}
//为了和其他排序的接口相同,加了上面的辅助函数 
void Quick_sort(int a[],int n){
	Qsort(a,0,n-1);
} 
/*简单选择排序
简单选择排序是选择排序中最简单的排序方法
其基本思想是,第i趟排序在待排序区间r[i]~r[n]
中选取关键码最小的记录,并和第i个记录交换
作为有序序列的第i个记录*/
void Select_sort(int a[],int n){
	for(int i=0;i<n;i++){
		int k=i;
		for(int j=i+1;j<n;j++){//无序区选择一个最小的 
			if(a[j]<a[k]){
				k=j;//标记最小的那个下标 
			}
		}
		if(k!=i){
			swap(a[i],a[k]);
		} 
	}
} 
/*堆排序
堆排序是简单选择排序的一种改进,
改进的着眼点在于,如何减少关键码的比较次数
简单选择排序实在一趟排序中仅选出最小关键码,没有把一趟比较结果保存下来*/

void shift(int a[],int k,int m){//n-1
	//k为根的编号,m为最后一个叶子的编号
	int i=k;
	int j=i*2+1;//左孩子 
	int x=a[i];//保存好当前元素
	while(j<=m){
		if(j<m&&a[j]<a[j+1]){
			j++;//j指向较大的那个 
		}
		if(x>a[j]){//已经比较大的大,则已经成为了较大堆 
			break;
		}else{
			a[i]=a[j];
			i=j;
			j=i*2+1; 
		} 
	} 
	a[i]=x; 
} 
//堆排序,下标从1开始 
void Heap_sort(int a[],int n){
	for(int i=n/2;i>=0;i--){//初始建堆,从最后一个分支,一直到根节点 
		shift(a,i,n-1);
	}
	for(int i=n-1;i>=1;i--){
		swap(a[i],a[0]);//把最大的节点a[1]放到最后面
		shift(a,0,i-1);//只有第一个顶点不一定满足大根堆 
	} 
}
void show(int a[],int n){
	for(int i=0;i<n;i++){
		cout<<a[i]<<'\t';
	}
	cout<<endl;
}
int main(){
	int a[]={1,2,11,1,1,7,9,21,23,9};
//	Insert_sort(a,10);
//	Shell_sort(a,10);
//	Bubble_sort(a,10);
//	Quick_sort(a,10);
//	Select_sort(a,10);
	Heap_sort(a,10);
	show(a,10);
} 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值