演算法導論第七章快速排序

2022-02-04 00:42:57 字數 3027 閱讀 7209

一、快速排序概述

關於快速排序,我之前寫過兩篇文章,一篇是寫vc庫中的快排函式,另一篇是寫了快排的三種實現方法。現在再一次看演算法導論,發現對快速排序又有了些新的認識,總結如下:

(1)、快速排序最壞情況下的時間複雜度為o(n^2),雖然最壞情況下效能較差,但快排在實際應用中是最佳選擇。原因在於:其平均效能較好,為o(nlgn),且o(nlgn)記號中的常數因子較小,而且是穩定排序。

(2)、快速排序的思想和合併排序一樣,即分治。快排排序的分治思想體現在:

a、首先從待排序的數中選擇乙個作為基數,基數的選擇對於排序的效能有很大的影響,也是快排改進的關鍵所在。

b、分治,將比基數小的數放在左邊,比基數大的數放在右邊。

c、對分出來的兩個分割槽分別執行上一步,直到區間只有乙個數為止。

二、hoare(霍爾)排序

快速排序首先由 c. a. r. hoare(東尼霍爾,charles antony richard hoare)在2023年提出,之後又有許多人做了進一步的優化。見書本習題7-1。

霍爾排序思路:採用數列第乙個數作為基數,然後在數列的收尾兩端分別設定兩個「哨兵」,兩個哨兵分別向中間探測比基數大、小的數,然後進行交換。如下圖展示:

下面是霍爾排序的**:

1

int hoare_partition(int arr, int left, int

right)2

14swap(arr[left], arr[i]);

15return

i;16}17

18void hoare_quicksort(int arr, int left, int

right)

1925 }

三、演算法導論講述的快排和霍爾排序不同的是,演算法導論上實現的快排選取待排序數列的最後乙個數作為基數,然後也設定兩個哨兵,但這兩個哨兵是從頭到尾一起前進探測的。如果探測到乙個數比基數小,就把該數移到左邊,自然右邊就成了最大的數了。**如下:

1

int partition(int arr, int left, int

right)211

}12 swap(arr[right], arr[i+1]); //

!!!note: can't use temp:local variable

13return i+1;14

}1516void quicksort(int arr, int left, int

right)

1723 }

四、快排的優化版本如前所述,影響快排效能最大的因素在於基數的選取,雖然不管基數如何選取,演算法最壞情況下時間複雜度都還存在,但能夠減少常數項因子,從而優化了演算法效能。下面引述下書上介紹的幾種優化機制:

1、隨機優化:

因為快排中partition所產生的劃分中可能會有」差的「,而劃分的關鍵在於主元a[r]的選擇。我們可以採用一種不同的、稱為隨機取樣的隨機化技術,把主元a[r]和a[p..r]中隨機選出乙個元素交換,這樣相當於,我們的主元不在是固定是最後乙個a[r],而是隨機從p,...,r這一範圍隨機取樣。這樣可以使得期望平均情況下,partition的劃分能夠比較對稱。

2、中位數優化法:

所謂「三數取中」是指,從子陣列中隨機選出三個元素,取其中間數作為主元,這算是前面隨機化版本的公升級版。雖然是公升級版,但是也只能影響快速排序時間複雜度o(nlgn)的常數因子。見習題7-5.

3、遞迴棧的優化:

quicksort演算法包含兩個對其自身的遞迴呼叫,即呼叫partition後,左邊的子陣列和右邊的子陣列分別被遞迴排序。quicksort中的第二次遞迴呼叫並不是必須的,可以用迭代控制結構來代替它,這種技術叫做「尾遞迴」,大多數的編譯器也使用了這項技術。

模擬的尾遞迴:

**實現:

1

//隨機優化版本2//

get random num between m and n;

3int random(int m, intn)4

91011void random_quicksort(int arr, int left, int

right)

12

1

//中位數優化,下面乙個獲取中位數的函式2//

get mid num of a,b,c;

3int midnum(int a, int b, intc)4

1

//模擬尾遞迴

2void tail_recursive_quicksort(int arr, int left, int

right)39

}1011//

尾遞迴優化

12void tail_recursive_quicksort_optimize(int arr, int left, int

right)

1320

else24}

25 }

此外,還有一些其他的方法,比如,將遞迴的方式改成非遞迴,還有習題7-6提出的區間模糊排序法:我們無法準確知道待排序的數字是什麼,但知道它屬於實數軸上的某個區間,也就是知道形如[ai, bi]的閉區間。我們可以對這些區間進行排序,感興趣的可以自己實現下。

演算法導論 第七章《快速排序》

本章介紹了快速排序及其演算法分析,快速排序採用的是分治演算法思想,對包含n個數的輸入陣列,最壞情況下執行時間為 n 2 但是平均效能相當好,期望的執行時間為 nlgn 另外快速排序能夠就地排序 我理解是不需要引入額外的輔助空間,每次劃分能確定乙個元素的具體位置 在虛擬環境中能很好的工作。快速排序演算...

演算法導論 第七章 快速排序

快速排序通常是實際應用中最好的選擇,因為它的平均效能非常好,它的期望時間複雜度為o nlng 而且隱含的常數因子非常小。另外,它還是原址排序。quicksort a,p,r if p隨著程式的執行,陣列被劃分為4個 小於主元,大於主元,未劃分,主元,可能有空的 區域。對於partition中的第3 ...

演算法導論 第七章 快速排序

1.快速排序描述 基於分治模式,分為分解 解決和合併三部分 1 分解 將陣列a p.r 劃分為兩個子陣列a p.q 1 和a q 1.r 是的a p.q 1 中每個元素都小於或等於a q 2 解決 通過遞迴呼叫快速排序,對子陣列a p.q 1 和a q 1.r 排序 3 合併 合併兩個有序的陣列,a...