10 3交換排序(2)快速排序

2021-08-14 19:33:10 字數 2280 閱讀 8273

快速排序也是乙個典型的分治思想(divide and conquer)的運用。對於分治法需要了解如下的乙個流程:

1.將當前的大問題分解成若干個子問題

2.解決每乙個子問題

3.合併子問題的解

對於運用到陣列的排序來說,很顯然可以將陣列一分為二,分別將其左右排序完成後,再對整個陣列進行排序。上面描述的便是歸併排序的一般思路。

而對於快速排序則略有不同:先選取乙個樞軸量pivot,將陣列分為三塊:[l][pivot][r],其中[l]表示當前陣列比樞軸量值都小的元素,而[r]表示比樞軸量都大的元素。這就完成了第一步分解的過程。然後分別對這l,r兩個子陣列進行快速排序,這就是第二部解決的過程。由於是原址排序,最後一步合併子問題解的過程可以省略。(原址的問題下面回敘述。)

因此,快速排序涉及到的核心問題在於如何選取乙個恰當的樞軸量和如何對陣列進行劃分。在教材的實現中,往往取a[

1]也就是第乙個元素作為樞軸。當然作為改進的辦法是,每次隨機從陣列中選取乙個元素作為樞軸。選取完樞軸以後,需要進行劃分,也就是將樞軸放到乙個恰當的位置,使樞軸左邊的元素都比樞軸小,而右邊的元素都比其大。劃分的過程在2.2節順序表的一些演算法設計中也有敘述,這裡略去了。

這裡使用了hoare的劃分方法實現了快速排序。hoare方法的思想在於兩邊往中間夾,遇到不滿足預定條件的就交換位置。在兩邊夾的過程中要確保兩頭指標

i 和

j不能錯位、越界。需要注意一點的地方在於遞迴出口要考慮清楚。

/**

* 快速排序

* @param std::vector<_ty> & a 待排序的陣列a

* @param int begin 需要排序的子陣列的起始元素的下標

* @param int end 需要排序的子陣列的末尾元素的下標

*/template

void quick_sort(std::vector

<_ty> & a, int begin, int end)

a[i] = pivot;

output_list(a);

//遞迴進行子陣列排序

quick_sort(a, begin, i - 1);

quick_sort(a, i + 1, end);

}

對於遞迴的演算法很難直接輸出每一次迭代的情況,因此只在每次劃分完成後進行一次輸出,觀察其排序情況。對於測試資料5 4 11 18 1 70 35 90 100 2可以得到如下輸出:

2       4       1       5       18      70      35      90      100     11

1 2 4 5 18 70 35 90 100 11

1 2 4 5 11 18 35 90 100 70

1 2 4 5 11 18 35 90 100 70

1 2 4 5 11 18 35 70 90 100

1 2 4 5 11 18 35 70 90 100

一般情況下認為快速排序的平均時間複雜度是o(

nlogn)

,最壞時間複雜度o(

n2) 。由於遞迴要考慮棧深度問題,因此平均的空間複雜度是o(

logn

) ,最壞空間複雜度是o(

n)。

不難理解平均的情況。每次選取樞軸量恰好將陣列等分,因此就得到了乙個高度為

logn

的遞迴樹。最壞情況則發生在,每次選取樞軸量後得到的劃分,樞軸量恰好位於陣列邊緣位置(a[

1]或a[n

] ),這樣這棵遞迴樹就會退化為一邊倒的一棵二叉樹。對於每次選取第乙個元素或者最後乙個元素作為樞軸進行劃分的情況下,在資料幾乎有序的情況下,快速排序會退化的非常低效。所以樞軸的選擇一般採取更好的方法。而對於隨機選取的樞軸來說,期望時間也是o(

nlgn)

,最壞情況同樣是o(

n2)

交換排序 2 快速排序

快速排序 快速排序的基本演算法思想是 設待排序的元素序列個數為 n,存放在陣列 a中,令第乙個元素為樞軸元素,即將 a 0 作為參考元素,令 pivot a 0 初始時,令 i 0 j a.legth 1 然後按以下方法操作 1 從序列的 j位置往前,依次將陣列的中的元素與樞軸元素相比較,如果當前元...

交換排序 快速排序

快速排序 quick sort 也是一種交換排序,它在排序中採取了分治策略。從待排序列中選取一元素作為軸值 也叫主元 將序列中的剩餘元素以該軸值為基準,分為左右兩部分。左部分元素不大於軸值,右部分元素不小於軸值。軸值最終位於兩部分的分割處。對左右兩部分重複進行這樣的分割,直至無可分割。從快速排序的演...

交換排序 快速排序

簡述 快速排序可以說算是針對氣泡排序的一種優化,氣泡排序是順序交換,這樣交換次數順序增長。如果我們做跳躍的交換,那麼可以使得交換次數也是跳躍性,會有所降低 演算法思想 找出乙個樞軸,用於做比較交換,並記下後用。一般用第乙個 用第 一 中間 最後三個取中後來效果會更好 定乙個高位 high和底位 lo...