排序算法5----快速排序(挖坑法)(C语言)

        bd35845be6dd4711a1e111251c4ecab8.png

        快排时间复杂度:O(NlogN) ,快速排序的空间复杂度为O (log n),其中n为待排序数组的长度。 这是因为快速排序是一种原地排序算法,它通过在原始数组上进行交换和划分操作来实现排序,而不需要额外的空间来存储临时数据。 在每一次递归调用中,快速排序只需要使用O (log n)的额外空间来保存递归调用的栈空间

        挖坑法是基于Hoare版本的一种改良(改良单趟排序时的方法),其本质是类似的。先来个图自己感受一下。

f4deacf87adb4a3f99c7d545be993a81.gif

0591bfe83989434e89917d93db13236c.png

edba48055d0f4d8591492b48ca449f8d.png 89cf917b567443f593211d75aef02fca.png

 9c31c823b7f14c48817e1bb5d54e8316.png

 5c34d3d476024cf0977ce318fee6b741.png

 20f3108d9e494955952ab21e1c43a38d.png

        将基准值设为“坑”,然后右边先走,找小,找到小的后,将“小”填入坑,再将原来小的位置,重置为坑,接着左边走。直到left和right相遇时,一定相遇为“坑”(因为left和right始终有一个为坑,那么坑左边为小,右边为大,再将key放入坑中),循环结束。

        同样,我们采取“三数取中”法来进行优化:

//这样可以有效的提高效率
//避免每次单趟排序时的begin元素都是最大或最小
int GetMidi(int* arr, int begin, int end)
{
	int midi = (begin + end) / 2;
	if (arr[begin] < arr[end])
	{
		if (arr[midi] >= arr[begin] && arr[midi] <= arr[end])
			return midi;
		if (arr[midi] >= arr[end])
			return end;
		if (arr[midi] <= arr[begin])
			return begin;
	}
	else
	{
		if (arr[midi] >= arr[end] && arr[midi] <= arr[begin])
			return midi;
		if (arr[midi] >= arr[begin])
			return begin;
		if (arr[midi] <= arr[end])
			return end;
	}
}

         然后进行单趟排序:将基准值排到中间,最后返回此时基准值的下标。

//单趟
int SingleQuick_DigHole(int* arr, int begin, int end)
{
	int key = arr[begin]; //取定基准值
	int holei = begin; //定义“坑”的下标
	int left = begin, right = end;
	while (left < right)
	{
		//同理右边先走,右找小
		while (left < right && arr[right] >= key)
		{
			right--;
		}
		//找到小后,将这个小的值挪到“坑”里面去,然后right变成新的坑
		arr[holei] = arr[right];
		holei = right;

		//左找大
		while (left < right && arr[left] <= key)
		{
			left++;
		}
		//找到大后,将这个大的值挪到“坑”里面去,然后left变成新的坑
		arr[holei] = arr[left];
		holei = left;
	}
	//最后当left和right相遇时,必定是在坑处相遇,将基准值挪到“坑”里面,然后返回坑的下标
	arr[holei] = key;
	return holei;
}

        最后递归[begin,keyi-1]和[keyi+1,end]:

void QuickSort_DigHole_incline(int* arr, int begin, int end)
{
	if (begin >= end)
		return;

	int midi = GetMidi(arr, begin, end);
	Swap(&arr[begin], &arr[midi]);

	int keyi = SingleQuick_DigHole(arr, begin, end);

	//继续递归坑的左区间和右区间
	//[begin,keyi-1] , [keyi+1,end]
	QuickSort_DigHole_incline(arr, begin, keyi - 1);
	QuickSort_DigHole_incline(arr, keyi + 1, end);
}

        “挖坑法”和Hoare的办法从本质上来说是一致的,差别就是在单趟排序的方法不同,理解好了Hoare版本的单趟排序,那么对“挖坑法”理解难度就不大了。

  • 10
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

夹心宝贝

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值