C语言---快速排序实现三种方法 ---- 挖坑法----递归求解(含三数取中)

第一种,挖坑法:

顾名思义,挖坑法,首先要有一个"坑",现在我们将第一个数字取出放到key中,现在6这个位置就是一个可以被覆盖的位置,也就是一个坑位,设开始位置为begin,末尾位置为end,现在我们从end找比key小的数字,也就是2的这个位置开始找,2比6小.那么就将2移动到6的位置上,变为:

 

这时的坑位被2填补上了,那么新的坑位就是原来2的位置,现在我们从begin再找比key大的数字,找到了8,将8放到坑位 变为:

以此类推,再从后面找比key小的,然后放到坑位,原来的位置变成新的坑位, 一直找到end与begin相遇,或者begin>end,为什么是begin>=end时就不找呢,begin是是找比key大的,当他遇到end说明前面都是比key小的,这时我们的目的就已经达成了,end同理

,

那么最后再将key,也就是6放到坑位当中,就会发现,前面的数都比6小,后面的数都比6大,这就代表6这个数已经在属于他排好后的位置上了,那么6这个数字就被排好了

 那么既然6的左边都比6小,6的右边都比6大,那么是不是就代表着,左边排好,右边也排好,那么整个排序排好了? 是的,那我们就应该像6那样,把每一个数字都排到属于他的位置上,因为6已经排好,所以这时的区间要有所改变,从2 到1 是一个区间,从7 到 8是一个区间,这时左边区间的begin和end分别为2的位置和1的位置了,我们先将2放到属于他的位置上,结果为

 那么我们将这个区间再进行划分,分为2的左区间和右区间,左区间的只有一个1,说明他就已经是有序的了,那我们就不再管他,以同样的方式去排右区间,最终6的左边就排好了,那么右边也以同样的方法实现即可,实现的方法一种是循环实现,一种是递归实现,这里我们先采用递归实现

int Getmid(int* arr, int left, int right)//三数取中法
{
	int mid = (left + right) >> 1;
	if (arr[left] < arr[mid])
	{
		if (arr[mid] < arr[right])
			return mid;
		else if (arr[left] > arr[right])
			return left;
		else
			return right;
	}
	else
	{
		// arr[left] > arr[mid]
		if (arr[left] < arr[right])
			return left;
		else if (arr[mid] > arr[right])
			return mid;
		else
			return right;
	}
}
void Swap(int* a1, int* a2)
{
	int temp = *a1;
	*a1 = *a2;
	*a2 = temp;
}
int Quick_Pit_Sort(int* arr, int left, int right)
{

//当数组接近有序的时候,如果再默认坑为开始第一位数的话效率就会很低,三数取中法就
//可以解决这种问题,顾名思义,就是在区间内去掉最大数和最小数,有效的提高了接近有序时的效率
	int Index = Getmid(arr,left,right);
	Swap(&arr[left],&arr[Index]);
	int begin = left;
	int end = right;
	int pit = begin;
	int key = arr[begin];
	while (begin < end)
	{
		while (begin < end && arr[end] >= key)
			--end;
		arr[pit] = arr[end];
		pit = end;

		while (begin < end && arr[begin] <= key)
			++begin;
		arr[pit] = arr[begin];
		pit = begin;
	}
	arr[pit] = key;
} 

void Quick_Sort(int* arr, int left, int right)
{
	if (left >= right)
		return;
	int keyIndex = Quick_Pit_Sort(arr, left, right);
	Quick_Sort(arr,left,keyIndex-1);
	Quick_Sort(arr,keyIndex+1,right);
	
}

这里还需要说一下三数取中法,由于当需要排序的内容接近或者已经有序的时候,这时取到的都是最大值或者最小值,挖坑法的坑位就会一遍遍的遍历,不发生交换或者很少发生交换,时间复杂度就会达到O(N^2),这种情况下使用三数取中法即可避免取到最大值或者最小值

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值