圖解快速排序(Quick Sort)

快速排序(Quick Sort)

快速排序是由東尼·霍爾所發展的一種排序算法。在平均狀況下,排序 n 個項目要 Ο(nlogn) 次比較。在最壞狀況下則需要 Ο(n2) 次比較,但這種狀況並不常見。事實上,快速排序通常明顯比其他 Ο(nlogn) 算法更快,因爲它的內部循環(inner loop)可以在大部分的架構上很有效率地被實現出來。

快速排序使用分治法(Divide and conquer)策略來把一個串行(list)分爲兩個子串行(sub-lists)。快速排序又是一種分而治之思想在排序算法上的典型應用。

快速排序的名字起的是簡單粗暴,因爲一聽到這個名字你就知道它存在的意義,就是快,而且效率高!它是處理大數據最快的排序算法之一了。雖然 Worst Case 的時間複雜度達到了 O(n²),但是人家就是優秀,在大多數情況下都比平均時間複雜度爲 O(nlogn) 的排序算法表現要更好。快速排序的最壞運行情況是 O(n²),比如說順序數列的快排。但它的平攤期望時間是 O(nlogn),且 O(nlogn) 記號中隱含的常數因子很小,比複雜度穩定等於 O(nlogn) 的歸併排序要小很多。所以,對絕大多數順序性較弱的隨機數列而言,快速排序總是優於歸併排序。

C++的標準庫sort函數就是基於快速排序實現的,當然實現要複雜的多,裏面有各種優化,當數據量比較少的時候採用的是插入排序。雖然C中的qsort函數也是基於快排的,但是sort要比qsort快的多。

算法描述

快速排序使用分治法來把一個串(list)分爲兩個子串(sub-lists)。具體算法描述如下:

  • 從數列中挑出一個元素,稱爲 “基準”(pivot);
  • 重新排序數列,所有元素比基準值小的擺放在基準前面,所有元素比基準值大的擺在基準的後面(相同的數可以到任一邊)。在這個分區退出之後,該基準就處於數列的中間位置。這個稱爲分區(partition)操作;
  • 遞歸地(recursive)把小於基準值元素的子數列和大於基準值元素的子數列排序。

動圖演示

 

代碼實現

1.常規挖坑法(基於數據結構嚴蔚敏版)

// 快排挖坑法
int partition(vector<int> &v, int l, int r)
{
    int pivot = v[l];
    int low = l, high = r;

    while (low < high) {
        while (low < high && v[high] >= pivot) { --high; }
        v[low] = v[high];

        while (low < high && v[low] <= pivot) { ++low; }
        v[high] = v[low];
    }

    v[low] = pivot;

    return low;
}

void quickSort(vector<int> &v, int l, int r)
{
    if (l < r) {
        int pivot = partition(v, l, r);
        quickSort(v, l, pivot - 1);
        quickSort(v, pivot + 1, r);
    }

}

2.交換法(網上大神模板)

void quickSort(vector<int> &v, int l, int r)
{
    if (l >= r) return;

    int pivot = v[(l + r) >> 1];
    int low = l - 1, high = r + 1;

    while (low < high) {
        do --high; while (v[high] > pivot);
        do ++low; while (v[low] < pivot);

        if (low < high) swap(v[low], v[high]);
    }
    quickSort(v, l, high);
    quickSort(v, high + 1, r);
}

算法分析

快速排序每次選取基準元素劃分的時候期望把序列分成大小相同的兩個序列,即期望爲O(nlogn)的,但如果輸入序列爲順序序列,則每次劃分的元素都將處於基準元素(此時基準元素每次取首元素或尾元素)的一邊,這樣就退化爲O(n2)的。所以,快速排序的平均時間複雜度爲O(nlogn),最壞時間複雜度爲O(n2)。它的時間複雜度跟輸入序列和選取的基準元素有關。空間複雜度主要是進行遞歸時消耗的棧空間,所以空間複雜度爲O(logn)。快速排序是不穩定排序。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章