vlambda博客
学习文章列表

快速排序 | 失踪人口回归 | 快速排序 快不快?

快速排序-Quick Sort

基础版本--后续有机会出详细优化版本

  • 快速排序由于排序效率在同为 的几种排序方法中效率较高,因此经常被采用。
  • 再加上快速排序思想----分治法也确实实用,因此很多软件公司的笔试面试,包括像腾讯,微软等知名IT公司都喜欢考这个,还有大大小的程序方面的考试如软考,考研中也常常出现快速排序的身影。
  • 总的说来,要直接默写出快速排序还是有一定难度的,因此本人就自己的理解对快速排序作了下白话解释,希望对大家理解有帮助,达到快速排序,快速搞定。

快速排序 | 失踪人口回归 | 快速排序 快不快?
快速排序

- 算法思想:

  • 快速排序是冒泡排序的改进算法。它也是通过不断比较和移动交换来实现排序的,只不过它的实现增大了记录的比较和移动的距离, 将关键字较大的元素直接放到枢轴元素(随机或者特定位置的元素)后面,关键字较小的元素直接放到枢轴元素前面,从而减小了比较次数和交换次数
  • (1)选择基准:在待排序列中,按照某种方式挑出一个元素,作为 "基准"(pivot) 注: 此处选择中间位置元素为 pivot 元素
  • (2)分割操作:以该基准在序列中的实际位置,把序列分成两个子序列。此时,在基准元素左边的元素都比基准元素小,在基准元素右边的元素都比基准元素大。
  • (3)递归地对两个序列进行快速排序,直到序列为空或者只有一个元素。

实例演示

快速排序 | 失踪人口回归 | 快速排序 快不快?
待排序元素
快速排序 | 失踪人口回归 | 快速排序 快不快?
所有待排序元素(10 5 52 1 9)
快速排序 | 失踪人口回归 | 快速排序 快不快?
待排序元素(10 5 9 1)
待排序元素(1 5)

- 后续操作类似,不再演示

---

最终有序序列

代码如下:

// int a[] 待排序数组
// int left 数组左边界
// int right 数组右边界
//快速排序
void quick_sort(int a[], int left, int right) {
    //数组为空或者只有一个数
    if (left >= right)
        return;

    //分界点,枢轴元素(中间位置元素)
    int pivot = a[left + right >> 1];

    //两侧指针(数组两边界之外, i j 同时往中间移动)
    int i = left - 1, j = right + 1;

    //不断循环
    while (i < j) {
        //左右指针向中间移动
        do {
            i++;
        } while (a[i] < pivot);  //遇到第一个大于等于 pivot的值
        do {
            j--;
        } while (a[j] > pivot);  //遇到第一个小于等于 pivot的值

        //没有相遇
        if (i < j)
            //交换a[i], a[j]
            swap(a[i], a[j]);  // swap 函数在冒泡排序函数中已出现过
    }
    //递归处理左右两端
    quick_sort(a, left, j);
    quick_sort(a, j + 1, right);
}

1.3    算法总结

  • 在最优情况下,Partition(划分)每次都划分得很均匀,如果排序 个关键字,其递归树的深度就为 表示不大于 的最大整数),即仅需递归 次,需要时间为 的话,第一次 Partiation 应该是需要对整个数组扫描一遍,做 n 次比较。然后,获得的枢轴将数组一分为二,那么各自还需要 的时间 (注意:是最好情况,所以平分两半)
  • 于是不断地划分下去,我们就有了下面的不等式推断:

  • 在最优的情况下 ,快速排序的时间复杂度为


  • 在最坏的情况下 , 待排序的序列为正序或者逆序,每次划分只得到一个比上一次划分少一个记录的子序列, 注意: 另一个为空。如果递归树画出来,它就是一棵斜树。此时需要执行 次递归调用,且第 次划分需要经过 次关键字的比较才能找到第 个记录,也就是枢轴的位置,因此比较次数为:

  • 在最坏情况下 快速排序时间复杂度为


  • 平均的情况 ,设枢轴的关键字应该在第 的位置 ,那么:

  • 平均情况下, 快速排序时间复杂度为


  • 空间复杂度分析: 主要是递归造成的栈空间的使用,最好情况,递归树的深度为 ,其空间复杂度也就为 ,最坏情况,需要进行 次递归调用,其空间复杂度为 ,平均情况,空间复杂度也为


 
  • 稳定性分析: 由于关键字的比较和交换是跳跃进行的,快速排序是不稳定的。