演算法基礎4 快速排序

2021-07-22 22:01:51 字數 2595 閱讀 7275

快速排序也是在面試中常被問的排序演算法之一,它與歸併演算法一樣,也使用了分治的思想。快速排序的三步分治過程:

分解:將乙個待排序陣列a[p,…,r]劃分為兩個字陣列(可能為空)a[p…q-1], a[q+1…r],其中a[p…q-1]中的每乙個元素都小於a[q], a[q+1…r]中的每乙個元素都大於a[q]。計算下標q也是劃分過程中的一部分。

解決: 通過遞迴呼叫快速排序,對子陣列a[p…q-1]和a[q+1…r]進行排序。

合併:因為子陣列都是原址排序的,所以不需要合併操作,陣列a[p…r]已經有序。

下面先給出快速排序的偽**:

quicksort(a, p, r)

1.if p4. q = partition(a,p,r)

5. quicksort(a, p, q-1)

6. quicksort(a, q+1, r)

partition(a, p, r)

7. x = a[r] //選定的基準值

8. i = p-1

//類似乙個指標,指定要交換的元素

9.for j = p to r //也類似乙個指標,指定後面滿足交換條件的元素

10.if a[j] <= x

11. i ++

12. exchange a[i] with a[j]

13. exchange a[i+1] with a[r]

14.return i+1

在子陣列a[p…r]上,partition維護了4個區域,如下圖所示,a[p…i]區間內的所有值都是小於等於x,a[i..j]區間內的所有值都是大於x,a[r]=x。字陣列a[j…r-1]中的值可能屬於任何一種情況。

當a[j..r]中的元素小於等於x時,執行如演算法中的操作,i++,並且交換a[i]和a[j]。元素大於x時,沒有明顯操作,即加入到a[i..j]中。

js**如下:

var partition = function

(a,l,r)

}var ans = a[i+1];

a[i+1] = a[r];

a[r] = ans;

return i+1;

}var quicksort=function

(a,l,r)

}function

main

()console.log(main());

還有乙個過程,就是演算法的時間複雜度分析,雖然我們常說快速排序的時間複雜度是o(nlgn),卻很少具體的分析一下什麼情況下是o(nlgn),這個是快排最好的時間複雜度嗎?我們都知道快排的執行時間依賴於劃分是否平衡,而平衡與否又依賴於用於劃分的元素。如果劃分是平衡的,那麼快排演算法效能與歸併排序一樣。如果劃分不平衡,那麼快排的效能就接近於插入排序了。

下面從三個不同的劃分來分析一下快排的時間複雜性。

最壞情況劃分

當劃分的兩個字問題分別包含了n-1個元素和0個元素。我們假設每次遞迴呼叫都出現了這種不平衡的劃分。劃分操作的時間複雜度是o(n)。由於對大小為0的陣列進行遞迴會直接返回,因此t(0) = o(1),於是演算法執行的時間遞迴式可以表示成

t(n) = t(n-1)+o(n)

利用帶入法可以得到t(n) = o(n)+o(n-1)+o(n-2)+…+o(1)+t(0)

即:t(n) = o(n^2)

可以看到,最壞情況下快速排序執行時間並不比插入排序更好。此外,當陣列已經排好序時,時間複雜度依然為o(n^2),而插入排序的時間複雜度為o(n)。

最好情況劃分

在可能的最平衡的劃分中,partition得到的兩個子問題的規模都不大於n/2。這是因為其中乙個子問題的規模為[n/2],而另乙個子問題的規模為[n/2]-1。在這種情況下快速排序的效能非常好。此時,演算法執行的時間遞迴式為:

t(n) = 2t(n/2)+o(n)

上述遞迴式的解為t(n) = o(nlgn)。

事實上,任何一種常數比例的劃分都會產生深度為o(lgn) 的遞迴樹,其中每一層的時間代價都是o(n),因此,只要是常數比例的劃分,演算法的執行時間都是o(nlgn)。

平均情況

在平均情況下,partition所產生的劃分同時混合有「好」和「差」的劃分。此時,在遞迴樹中,好和差的劃分是隨機分布的。

如下圖a所示,顯示了連續兩層上的劃分,根節點處劃分的代價為n,劃分產生兩個子陣列,大小分別為n-1和0。在下一層上,大小為n-1的子陣列按最好情況劃分。這一組合的劃分代價為o(n)+o(n-1)= o(n)。該代價並不比(b)中所示的劃分情況差。因此,當好的劃分和差的劃分交替出現時,快速排序的時間複雜度與全是好的劃分時一樣,依然是o(nlgn)。區別只是o符號中隱含的常數因子要略大一些。

排序演算法4 快速排序

編寫乙份快速排序,完成對元素序列37,19,43,22,22,89,26,92按照從小到大順序排列。演算法思想 快速排序是氣泡排序演算法的改進,也屬於交換型別的排序演算法,它的基本思想描述如下 1 從第j個元素開始向前依次將每個元素與樞軸元素pivot比較。如果當前元素大於pivot,則比較前乙個元...

排序演算法 4 快速排序

快速排序法是對氣泡排序的一種改進,本來是要和氣泡排序寫在乙個文章裡的,不過前兩天剛開始在遞迴呼叫的時候沒有完全理解,昨天晚上google了一把發現原來自己理解錯了,我看的這個教材沒有寫清楚,今天早上除錯了一把終於成功。快速排序演算法的基本思想是 通過一趟排序將要排序的資料分割成獨立的兩部分,其中一部...

排序演算法 4 快速排序

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