排序算法---快速排序

背景

之前我们介绍的选择排序、插入排序、快速排序的时间复杂度都是O(n2),在数据量较大时效率较低。因此我们利用分治思想设计出了两种效率更高的算法:归并排序和快速排序。归并排序和快速排序的时间复杂度都是O(nlogn),且在大多数情况下,快速排序比归并排序效率更高。

原理

快速排序的基本思想是分治原理,具体操作如下:

1. 在待排序的数组中先选择一个数作为基准值,然后遍历整个数组,将小于基准值的元素放到基准值左边,将大于基准值的元素放到右边,这样就确定了基准值最后的正确位置。

2. 递归处理基准值左侧子数组和右侧子数组,直到数组中只剩下一个元素,这样就实现了整个数组的排序。

具体实现步骤

1. 选取待排序数组的第一个元素作为基准值iPivot,并定义iLeft和iRight分别指向待排序数组的最左侧和最右侧。

2. 判断iRight指向的元素值nums[iRight]是否大于基准值iPivot。若是,则iRight继续向左移动,iRight--;否则,将nums[iRight]存放到nums[iLeft]处。(注意,此时nums[iLeft]值已经被保存或者放到了其他地方,因此该处可以用于保存新的元素值

3. 判断iLeft指向的元素值nums[iLeft]是否小于等于基准值(带等于这样将等于基准值的元素都存放到基准值的左侧)。若是,则iLeft继续向右移动,iLeft++;否则,将nums[iLeft]存放到nums[iRight]处。(注意,此时nums[iRight]值已经被存放到其他地方,因此该处可以用于保存新的元素值

4. 重复步骤2、3,直到iLeft、iRight相遇。此时需要将之前定义的基准值iPivot保存到中间位置,即下标iLeft处,这样即实现了基准值iPivot左侧的值都小于等于基准值,基准值右侧的值都大于基准值,基准值iPivot即为最终需要保存的位置。

5. 分别对基准值iPivot左侧子数组和右侧子数组分别递归使用上述方法实现排序,直至单个待排序数组大小个数为1,最终实现了整个数组的排序。

代码实现

/* 区间为左闭右闭原则 */
void QuickSort(int* piArray, int iLeft, int iRight)
{
	int iCurLeft = iLeft;
	int iCurRight = iRight;
    /* 选取第一个元素作为基准值,这样遍历的时候需要从右侧开始遍历 */
	int iPivot = piArray[iLeft];        

	if (iRight < iLeft)
	{
		/* 当待排序数组只有一个元素时结束递归 */
		return;
	}

	while (iCurLeft < iCurRight)
	{
		/* 先从右侧开始遍历 */
		while ((iCurLeft < iCurRight) && (piArray[iCurRight] > iPivot))
		{
			iCurRight--;
		}
		/* 将右侧不符合条件元素保存到左侧 */
		piArray[iCurLeft] = piArray[iCurRight];

		/* 再从左侧开始遍历 */
		while ((iCurLeft < iCurRight) && (piArray[iCurLeft] <= iPivot))
		{
			iCurLeft++;
		}
		/* 将左侧不符合条件元素保存到右侧 */
		piArray[iCurRight] = piArray[iCurLeft];
	}

	/* 将基准值iPivot放到中间位置,保证左边小于等于基准值,右边大于基准值 */
	piArray[iCurLeft] = iPivot;

	/* 递归排序基准值左侧子数组 */
	QuickSort(piArray, iLeft, iCurLeft - 1);
	/* 递归排序基准值右侧子数组 */
	QuickSort(piArray, iCurLeft + 1, iRight);

	return;
}

参考:快速排序算法_elma_tww的博客-CSDN博客_快速排序算法

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值