[排序算法]C++实现快速排序

基本思想

  快速排序(Quick Sort)是对冒泡排序的一种改进。
  它的基本思想是,通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。
  假设待排序列为 {x0,x2,,xn1} { x 0 , x 2 , … , x n − 1 } ,首先任意选取一个记录(通常可选第一个记录)作为枢轴(pivot),然后将关键字比pivot小的都安置在它的位置之前,比pivot大的都放在它的位置之后。由此该枢轴最后所落的位置i作分界线将序列分成两个子序列 {x0,x1,,xi1} { x 0 , x 1 , … , x i − 1 } {xi+1,xi+2,xn1} { x i + 1 , x i + 2 … , x n − 1 } 。这个过程称为一趟快速排序(或一次划分)。


实现快速排序的步骤

  1. 将待排序列进行一趟快速排序,将序列一分为二。
  2. 对较小子序列递归排序
  3. 对较大子序列递归排序

一趟快速排序——交换步骤
附设两个指针iStart和iEnd,初值分别为待排序列的头和尾,枢轴的关键字为iPivotKey
1. 将枢轴记录保存起来
2. 从iEnd位置起向前搜索找到第一个关键字小于 iPivotkey的记录,对iStart指针所指位置的值覆盖
3. 从iStart位置起向后搜索找到第一个关键字大于 iPivotkey的记录,对iEnd指针所指位置的值覆盖
4. 只要符合iStart < iEnd,循环2和3步骤
5. 循环结束后,将第一步保存的枢轴记录归位,并返回枢轴位置


C++实现

/*
    交换iArr中子序列[iStart, iEnd]的记录,枢轴记录归位,并返回其所在位置
    此时在它之前的记录均不大于它,在它之后的记录均不小于它
*/
int Partition(int iArr[], int iStart, int iEnd)
{
    // 先将枢轴记录保存
    int iPivotKey = iArr[iStart];
    while (iStart < iEnd)
    {
        // 从iEnd位置起向前搜索找到第一个关键字小于iPivotkey的记录
        while (iStart < iEnd && iArr[iEnd]  > iPivotKey)
        {
            iEnd--;
        }
        iArr[iStart] = iArr[iEnd];

        // 从iStart位置起向后搜索找到第一个关键字大于iPivotkey的记录
        while (iStart < iEnd && iArr[iStart] < iPivotKey)
        {
            iStart++;
        }
        iArr[iEnd] = iArr[iStart];
    }

    iArr[iStart] = iPivotKey;  // 枢轴记录归位
    return iStart;             // 返回枢轴位置
}

void QuickSort(int iArr[], int iStart, int iEnd)
{
    if (iStart < iEnd)
    {
        int iPivot = Partition(iArr, iStart, iEnd); // 将序列一分为二
        QuickSort(iArr, iStart, iPivot - 1);        // 对低子序列递归排序
        QuickSort(iArr, iPivot + 1, iEnd);          // 对高子序列递归排序
    }
}

总结

时间复杂度
  通常,快速排序被认为是,在所有同数量级 O(nlogn) O ( n l o g n ) 的排序方法中,其平均性能最好。但是,若初始记录按关键字有序或基本有序时,快速排序将蜕化为冒泡排序,其时间复杂度为 O(n2) O ( n 2 )

空间复杂度
  快速排序需要一个栈空间来实现递归。
  若每一趟排序都将记录序列均匀地分割成长度相接近的两个子序列,则栈的最大深度为 log2n+1 ⌊ l o g 2 n ⌋ + 1
  若每趟排序之后,枢轴位置均偏向子序列的一端,则为最坏情况,栈的最大深度为n。

最坏时间复杂度最优时间复杂度平均时间复杂度空间复杂度
O(n2) O ( n 2 ) O(nlogn) O ( n l o g n ) O(nlogn) O ( n l o g n ) O(n) O ( n )

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值