C语言 - 快速排序基本思想及实现(含三路划分)

目录

1.快速排序基础思想

1.1快速排序基础实现

2.快速排序时间空间复杂度及弊端

3.快速排序优化 

4.针对大量相同数据数组的优化:三路划分思想 

1.快速排序基础思想

快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,其基本思想为:任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。总而言之就是两点:

1.将位于数组最左侧的值作为key,并将此数放到该放置的位置(排完序后所在的位置)

2.将数组中所有大于key的值放到key的右边,将所有小于key的值放到key左边

这里我们以数组{ 6 , 1 , 2 , 7 , 9 , 3 , 4 , 5 , 10 , 8 };为例,其中 6 为 key,我们用left 和 right 分别表示数组的最左侧下标 0 与数组最右侧下标 9。这里需要让右侧先走,这样才能保证他们相遇的地点即为key排序后应到的位置。

由于 8 大于key(6),因此 right--,同理,因为 10 大于 6 ,不需要换到前面,因此 right--,现在 right 指向 5 ,小于 key ,此时 left 开始动但是left一定要从最左侧开始动,也就是key的位置开始动,如果 left 从 1 开始动,后面递归到数组仅有两个数时,会因为一开始 left 和 right 就指向同一个位置而导致排序错误。

left指向key 6 因为不大于 key ,所以 left++ ,因为 1 、2 都小于key ,因此left++ 两次,指向 7 ,此时交换 left 与 right 的值,此时数组变成如下:

{ 6 , 1 , 2 , , 9 , 3 , 4 , 7 , 10 , 8 } (红色表示发生交换的两个数)

随后重复上述操作,right 找到小于 key 的 4 ,left 找到大于 key 的 9 ,随后两者交换结果如下

{ 6 , 1 , 2 , 5 , 4 , 3 , 9 , 7 , 10 , 8 } (红色表示发生交换的两个数)

随后 right 走到 3,left 也走到 3 ,此时因为left 与right 相遇,此时交换key与left/right位置的数据即可结束第一趟排序,所得数组如下:

{ 3 , 1 , 2 , 5 , 4 , 6 , 9 , 7 , 10 , 8 } (红色表示发生交换的两个数)

此时,6 已经移动到了最终位置,无需再移动,而左右两侧也分别是小于 6 的数组与大于 6 的数组,此时将数组拆分开来分别进行单趟循环,得到以 3 为key的数组和以 9 为key的数组,然后继续递归,这样将数组不断拆分递归排序,直到拆的只剩一个数时停止递归,这样就能完成整个数组的排序。

1.1快速排序基础实现

基于上述基本思路,单趟排序代码实现如下:

	int key = arr[left];//保存key的值,用于比较
	int keyi = left;//记录key的下标,便于最后一次交换,将key放到应放位置
	while (right > left)
	{
		while (arr[right] >= tmp && right > left)
		{
            //右边找小,若没找到小则向左移动继续找小,直到找到小或者与left相遇
			right--;
		}
		while (arr[left] <= tmp && right > left)
		{
            //左边找大,若未找到大则向右移动,直到找到大或者与right相遇
			left++;
		}
		if (left != right)
		{
            //交换左右两值,使得小的放到前面,大的放到后面
			Swap(&arr[left], &arr[right]);
		}
	}
    //将key放到对应位置,一趟排序确定一个点的位置,并将其他数据根据与key的大小而分成前后两组 
	Swap(&arr[keyi], &arr[left]);

完成一趟排序后,则需要根据key的位置将数组分成两组再次分别进行单趟排序,此时需要key的下标,根据key的下标keyi的位置,分成的两组范围分别是: [left , keyi - 1] 与 [keyi + 1 , right],但由于之前的单趟排序中ÿ

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值