排序算法

#include<iostream>
using namespace std;

void out(int *arr,int len) {

	for(int i=0; i<len; i++) {
		printf("%d ",arr[i]);
	}
	printf("\n");
}

//简单排序:选择、冒泡、直接插入

/*
	选择排序:从无序区选择一个最值放进有序区。
*/
void choice(int *arr,int len) {
	for(int i=0; i<len-1; i++) {
		int min=arr[i];
		int k=i;
		for(int j=i+1; j<len; j++) {
			if(arr[j]<min) {
				min=arr[j];
				k=j;
			}
		}
		if(k!=i) {
			int temp=arr[k];
			arr[k]=arr[i];
			arr[i]=temp;
		}
	}
}

/*
	冒泡排序:动态排序,每一趟经过比较得到一个最值
*/
void bubble(int *arr,int len) {
	for(int i=0; i<len-1; i++) {
		for(int j=0; j<len-i-1; j++) {
			if(arr[j]>arr[j+1]) {
				int temp=arr[j];
				arr[j]=arr[j+1];
				arr[j+1]=temp;
			}
		}
	}
}

//直接插入排序:从原序列中逐一拿来建序;从端部一直比较,得到插入位置

void direct_insert(int *arr,int len) {
	if(len<1)return;
	for(int i=1; i<len; i++) {
		if(arr[i]<arr[i-1]) {
			int j=i-1;
			while(j>=0) {
				if(arr[i]>=arr[j]) {
					break;
				}
				j--;
			}
			int temp=arr[i];
			for(int k=i-1; k>=j+1; k--) {
				arr[k+1]=arr[k];
			}
			arr[j+1]=temp;
		}
	}
}

/*
	希尔排序(直接插入排序的改进):间隔gap分组,直到gap=1;对每个分组进行直接插入排序;
*/

void shell(int *arr,int len,int gap,int dgap) {
	if(len<1||gap>len||gap<1||dgap>gap) {
		printf("参数错误!\n");
		return;//条件
	}
	while(gap>=1) { //gap逐渐减小到1,分为gap组
		for(int i=0; i<gap; i++) {
			//对每一组进行直接插入排序
			for(int j=i; j<len; j=j+gap) {
				int t=arr[j];
				for(int k=j-gap; k>=0; k=k-gap) {
					if(t>=arr[k])break;
					int temp=arr[k+gap];
					arr[k+gap]=arr[k];
					arr[k]=temp;
				}
			}
		}
		gap=gap/dgap;
	}
}

/*
	快排(冒泡排序的改进):递归写法。
	一趟排序:选择分组的第一个元素作为标杆key,从后往前与 key比较和从前往后与key比较,将
	分成左边小于key的部分和key右边大于 key的部分。
	算法:注意临界数据
*/
void swap(int *arr,int v1,int v2) {
	int temp=arr[v1];
	arr[v1]=arr[v2];
	arr[v2]=temp;
}

void quick(int *arr,int l,int r) {
	if(l>=r)return;
	int key=arr[l];
	int i=l;
	int j=r;
	while(i!=j) {
		while(arr[j]>=key&&j>i) {
			j--;
		}
		swap(arr,i,j);
		while(arr[i]<=key&&j>i) {
			i++;
		}
		swap(arr,i,j);
	}
	quick(arr,l,i-1);
	quick(arr,i+1,r);
}
//快排的递推写法
void quick2(int *arr,int l,int r) {

}

/*
	堆排序算法(选择排序的改进):主要实现在结点下滑算法 。
	1. 初始堆(这里建成最大堆)
		将数组元素逻辑上构造成完全二叉树,在从非叶结点到根结点依次执行下滑。
	2. 调整堆
		将根结点和最后一个无序区叶结点交换,然后将交换后的叶结点归为有序区,直到有序区的个数为n-1;
*/
void glidedown(int *arr,int len,int index) {
	if(index>=len)return;
	if(index*2+1<len) { //有左海子
		if(index*2+2<len) { //并且有右孩子
			if(arr[index*2+1]<arr[index*2+2]) { //下滑到最大的那个孩子
				if(arr[index]<arr[index*2+2]) {
					swap(arr,index,index*2+2);
					glidedown(arr,len,index*2+2);
				}
			} else {
				if(arr[index]<arr[index*2+1]) {
					swap(arr,index,index*2+1);
					glidedown(arr,len,index*2+1);
				}
			}
		} else { //有左海子,没有右孩子
			if(arr[index]<arr[index*2+1]) {
				swap(arr,index,index*2+1);
				glidedown(arr,len,index*2+1);
			}
		}
	}
}

void heap(int *arr,int len) {
	//最后一个非叶结点下标
	int ny_index=(len-1-1)/2;
	//1. 造初始堆
	for(int i=ny_index; i>=0; i--) {
		glidedown(arr,len,i);
	}

	printf("初始堆:\n");
	out(arr,len);

	//2. 调整堆(从最后一个无序区结点开始调整,调整n-1次)
	int count=0;
	for(int j=len-1; j>=1; j--) {
		swap(arr,0,j);
		count++;
		int ny_index2=(j-1)/2;
		for(int k=ny_index2; k>=0; k--) {
			glidedown(arr,len-count,k);
		}
	}
}

/*
	归并排序:采用分治法。
	将两个有序的数列合并为一个有序数列
	合并算法:1. 有一个存放有序序列的空间
			  2. 两个指针分别指向两个有序数列起始位置
			  3. 将指针所比较的最值放进有序空间,指针移动
			  上面的2,3再循环完成两序列的合并 
*/ 

void merge_two(int *arr,int *temp,int start,int mid,int end){
	int i=start;
	int j=mid+1;
	int k=0;
	while(i<=mid&&j<=end){
		if(arr[i]<arr[j]){
			temp[k++]=arr[i++];
		}else{
			temp[k++]=arr[j++];
		}
	}
	while(i<=mid){
		temp[k++]=arr[i++];
	}
	while(j<=end){
		temp[k++]=arr[j++];
	}
	//注意这里 
	for(int h=0;h<k;h++){
		arr[start++]=temp[h];
	}
}

void merge(int *arr,int *temp,int start,int end){
	if(start>=end)return;
	int mid=(start+end)/2;
	merge(arr,temp,start,mid);
	merge(arr,temp,mid+1,end);
	merge_two(arr,temp,start,mid,end);
} 

/*
	排序算法选择:1.数据的量n的大小,2.数据的分布 3. 稳定性(是否改变原相同数值的相当位置) 
	1. 若n较小,可采用直接插入排序法或选择排序法
	2. 若n较小且数据分布有序,可以采用直接插入排序法或冒泡排序法
	3. 若n大,应采用快排,堆排序,或归并排序 
*/ 

int main() {
	int a[]= {10,4,5,8,3,2,1,7,6,9};
	//choice(a,10);
	//bubble(a,10);
	//direct_insert(a,10);
	//shell(a,10,10,2);
	//quick(a,0,9);
	//heap(a,10);
	printf("输出结果:\n");
	int temp[10];
	merge(a,temp,0,9);
	out(a,10);
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值