七大排序完整篇,C语言实现,简单易懂

冒泡排序

BubbleSort(T* d,const int n) {
	T temp;
	for (int i=0; i<n-1; i++) /* 外循环为排序趟数,len个数进行len-1趟 */
		for (int j=0; j<n-1-i; j++) { /* 内循环为每趟比较的次数,第i趟比较len-i次 */
			if (!comp(d[j],d[j+1])) { /* 相邻元素比较,若逆序则交换(升序为左大于右,降序反之) */
				temp = d[j];
				d[j] = d[j+1];
				d[j+1] = temp;
			}
		}
}

直接选择

SelectSort(T* d,const int n) {
	for (int i = 0 ; i < n - 1 ; i++) {
		int min = i;
		for (int j = i + 1; j < n; j++)     //走訪未排序的元素
			if (comp(d[j],d[min]))    //找到目前最小值
				min = j;    //紀錄最小值
		swap(&d[min], &d[i]);    //做交換
	}

直接插入

//直接插入排序
void InsertSort(T* d,const int n) {
	for(int i=1; i<n; i++) {
		int k=i-1;//有序序列最后一个数据的索引
		T a=d[i];//无序序列第一个数据
		while(k>=0&&comp(a,d[k])) { //数据逐一向后移位
			d[k+1]=d[k];
			k--;
		}
		d[k+1]=a;//将无序序列第一个数据置于有序序列中
	}
}

堆排序

HeapAdjust(T*d,int left,int right) {
	T a=d[left];//根结点
	for(int j=2*left+1; j<=right; j=2*j+1) { //2*left+1左叶
		if(j<right&&comp(d[j],d[j+1]))j++;//j+1右叶
		if(comp(d[j],a))break;//满足堆条件终止循环
		d[left]=d[j];//叶结点置于根结点
		left=j;//改变根索引为叶索引
	}
	d[left]=a;//根结点置于叶结点
}
void HeapSort(T* d,const int n) {
	for(int i=n/2-1; i>=0; i--)HeapAdjust(d,i,n-1); //建初始堆
	for(int i=n-1; i>0; i--) {
		swap(d[0],d[i]);//交换堆顶与堆尾元素
		HeapAdjust(d,0,i-1);//剩余元素重新建堆
	}
}

希尔排序

void ShellSort(T*d,const int n) {
	int h=1;
	while(h<n/3)h=h*3+1;//动态定义增量序列
	while(h>0)
//逐渐缩小增量h作直接插入排序
	{
		for(int i=h; i<n; i++) { //在当前增量h下对各子序列作直接插入排序
			int j=i-h;//当前子序列的有序序列最后一个元素的索引
			T a=d[i];//无序序列的第一个元素
			while(j>=0&&comp(a,d[j])) {
				d[j+h]=d[j];
				j-=h;
			}
			d[j+h]=a;//将d[i]插到j+h的位置
		}
		h=h/3;
	}
}

二路归并排序

//归并排序-非递归方式
void MergeSort(T*d,const int n) {
	int size=1,left,mid,right;//size为子序列长度
	T *w=new T[n];
	while(size<n) {
		left=0;//子序列左结点
		while(left+size<n) {
			mid=left+size-1;//子序列中间结点
			right=mid+size;//子序列右结点
			if(right>=n)right=n-1;//右序列长度小于size
			Merge(d,w,left,mid,right);//归并两子序列
			left=right+1;//下一次归并时左序列的首索引
		}
		size*=2;//序列长度增加一倍
	}
	delete[]w;
}//将序列[first,mid]和[mid+1,right]合并成一个有序序列
void Merge(T*d,T*w,int left,int mid,int right) {
	int i=left;//左序列起始位置
	int j=mid+1;//右序列起始位置
	int k=left;//辅助数组起始位置
	while(k<=right) { //两个有序序列最小元素先放入辅助数组
		if(i>mid)w[k++]=d[j++];
		else if(j>right)w[k++]=d[i++];
		else {
			if(comp(d[j],d[i]))w[k++]=d[j++];
			else w[k++]=d[i++];
		}
	}//将有序序列替换原有序列
	for(int k=left; k<=right; k++)d[k]=w[k];
}

快速排序

void QuickSort(T*d,const int n) {
	if(n<=1)return;
	const int M=7,NSTACK=128;//子序列长度小于7,采用插入排序
	int i,j,k,jstack=-1,left=0,mid,right=n-1;
	int istack[NSTACK];
	while(true) {
		if(right-left<M)//插入法排序
		{
			for(j=left+1; j<=right; j++) {
				T a=d[j];
				for(i=j-1; i>=left&&comp(a,d[i]); i--)d[i+1]=d[i]; //移位
				d[i+1]=a;//插入到准确位置
			}
			if(jstack<0)break;//排序终止
			right=istack[jstack--];//子序列右结点
			left=istack[jstack--];//子序列左结点
		} else//快速排序
		{
			i=left+1;//左指针
			j=right;//右指针
			k=i;//基准数的索引
//三元素中值点作为基准数,避免序列为正常序列
			mid=(left+right)/2;
			swap(d[mid],d[k]);
			if(comp(d[right],d[left]))swap(d[left],d[right]);
			if(comp(d[right],d[k]))
				swap(d[k],d[right]);
			if(comp(d[k],d[left]))
				swap(d[left],d[k]);
			while(true) {//先从右边开始寻找小于基准数的d[j]
				do j--;
				while(comp(d[k],d[j]));//再从左边开始寻找大于基准数的d[i]
				do i++;
				while(comp(d[i],d[k]));
				if(j<i)break;//交换d[j]和d[i]
				swap(d[i],d[j]);
			}
			swap(d[j],d[k]);//基准数归位
			jstack+=2;
			if(right-i+1>=j-left) { //右序列长度大于左序列长度
				istack[jstack-1]=i;//右序列左结点
				istack[jstack]=right;//右序列右结点
				right=j-1;//左序列右节点
			} else//左序列长度大于右序列长度
			{
				istack[jstack-1]=left;//左序列左结点
				istack[jstack]=j-1;//左序列右结点
				left=i;//右序列左节点
			}
		}
	}
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Devour123

愿每一份用功都可以得到回报

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值