O(n log n) - Quick Sort

From wiki
快速排序使用 divide-and-conquer 策略来把一个序列分为两个子序列(sub-lists)。

步骤为:

  1. 从数列中挑出一个元素,称为"基准"(pivot),
  2. 重新排序数列,所有比基准值小的元素摆放在基准前面,所有比基准值大的元素摆在基准后面(相同的数可以到任何一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
  3. 递归的把小于基准值元素的子数列和大于基准值元素的子数列排序。

递归到最底部时,数列的大小是零或一,也就是已经排序好了。这个算法一定会结束,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。

Pivot 例子

代码:

public void quickSort(int[] array) {
    if (array == null || array.length == 0) {
        return;
    }

    quickSortHelper(array, 0, array.length - 1);
}

private void quickSortHelper(int[] array, int start, int end) {
    if (start >= end) {
        return;
    }

    int midIndex = start + (end - start) / 2;
    int pivot = array[midIndex];  // pivot can be any random item in the array. Head is typically easier.
    int leftIndex = start;
    int rightIndex = end;
    while (leftIndex <= rightIndex) {
        while (array[leftIndex] < pivot) {
            leftIndex++;
        }
        while (array[rightIndex] > pivot) {
            rightIndex--;
        }
        if (leftIndex <= rightIndex) {
            swap(array, leftIndex, rightIndex);
            leftIndex++;
            rightIndex--;
        }
    }

    // 循环至此,array[leftIndex] >= pivot, array[rightIndex] <= pivot
    // start ~ rightIndex, 所有 items <= pivot
    // leftIndex ~ end, 所有 items >= pivot

    quickSort(array, start, rightIndex);
    quickSort(array, leftIndex, end);
}

时间复杂度:

  • Average: O(n log n)
  • Best: O(n log n)

Quick Sort 不可能比 O(n log n) 更好了。最好的情况,就是每次二分都是均匀二分,从而接近 log n 次递归。

  • Worst: O(n^2)

倒序或者顺序,每次取的pivot都为最大值或最小值。这种情况下,相当于 Selection sort 了

空间复杂度: No extra space。

Not stable.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 一、直接插入排序 直接插入排序(Insertion Sort)的基本思想是:每次将一个待排序的元素记录,按其关键字...
    kevin16929阅读 3,638评论 0 0
  • 排序算法说明 (1)排序的定义:对一序列对象根据某个关键字进行排序; 输入:n个数:a1,a2,a3,…,an 输...
    code武阅读 3,890评论 0 0
  • 十大经典排序算法 来源:https://github.com/wangguanfu/-Sorting-algori...
    星丶雲阅读 4,134评论 0 7
  • 简单排序 冒泡排序:循环遍历左右比较,较小者左移或较大者后移; 选择排序:在未排序序列中找到最小者元素一次放到已排...
    王然Gondole阅读 5,235评论 0 2
  • 没有人喜欢贫穷,但偏偏很多人穷困一生。 所有的贫穷,其实都来源一字:懒。 懒,并非特指身体的懒惰。身体的懒惰在贫困...
    小鱼儿ya阅读 4,927评论 0 0