快速排序的隨機化版本
比較排序
快速排序是一種原地排序演算法,對包含 n 個數的輸入陣列,最壞情況執行時間為 θ ( n2
)。雖然這個最壞情況執行時間比較差,但快速排序通常是用於排序的最佳的實用選擇。這是因為其平均效能相當好:期望的執行時間為 θ ( n lg n ),且 θ ( n lg n )記號中隱含的常數因子很小。
像合併排序一樣,快速排序也是基於分治模式的。下面是對乙個子陣列 a [ p .. r ]排序的分治過程的三個步驟:
分解:
陣列 a [
p ..
r ]被劃分成兩個(可能為空)子陣列
a [
p ..
q - 1 ]和
a [
q + 1 ..
r ],使得
a [
p ..
q - 1 ]中的每乙個元素都小於等於
a [
q ],而且,小於等於
a [
q + 1 ..
r ]中的元素。下標
q 也在這個劃分過程中計算。
解決:通過遞迴呼叫快速排序,對子陣列
a [
p ..
q - 1 ]和
a [
q + 1 ..
r ]排序。
合併:因為兩個子陣列是就地排序的,將它們合併不需要操作,整個陣列
a [
p ..
r ]已排序。
下面的過程實現了快速排序:
quick-sort(a, p, r)快速排序演算法的關鍵是1 if p < r
2 q = partition(a, p, r)
3 quick-sort(a, p, q - 1)
4 quick-sort(a, q + 1, r)
partition
過程,它對子陣列 a [ p .. r ]進行就地重排:
partition(a, p, r)1 x = a[r]
2 i = p - 1
3 for j = p to r - 1
4 if a[j] <= x
5 i = i + 1
6 exchange a[i] with a[j]
7 exchange a[i + 1] with a[r]
8 return i + 1
partition
總是選擇乙個 x = a [ r ]作為主元(pivot element),並圍繞它來劃分子陣列。在第3行到第6行中迴圈的每一輪迭代開始時,對於任何陣列下標k ,有
如果 p
<= k
<= i ,則 a [ k ] <= x
如果 i + 1 <= k
<= j - 1,則 a [ k ] > x
如果 k = r ,則 a [ k ] = x
下圖總結了這一結構。過程partition
作用於子陣列 a [ p .. r ]後得到四個區域。 a [ p .. i ]中的各個值都小於等於 x , a [ i + 1 .. j - 1 ]中的值都大於 x , a[ r ] = x 。 a [ j .. r - 1 ]中的值可以是任何值。
* 快速排序
*/public
static
void
quicksort(int array)
private
static
void
quicksort(int array, int
p, int
r) }
快速排序的執行時間與劃分是否對稱有關,而後者又與選擇了哪乙個元素來進行劃分有關。如果劃分是對稱的,那麼本演算法從漸近意義上來講,就和歸併排序演算法一樣快;如果劃分是不對稱的,那麼本演算法漸近上就和插入排序一樣慢。
快速排序的最壞情況劃分發生在劃分過程產生的兩個區域分別包含 n - 1個元素和1個0元素的時候。假設演算法的每一次遞迴呼叫都出現了這種不對稱劃分。劃分的時間代價為 θ ( n )。對乙個大小為0的陣列進行遞迴呼叫後,返回 t ( 0 ) = θ ( 1 ),故演算法的執行時間為 t ( n ) = t ( n - 1 ) + θ ( n )。最終得到解為 t ( n ) = θ ( n2
)。 在partition
過程可能的最平衡劃分中,乙個子問題的大小為floor(n / 2)
,另乙個子問題的大小為ceil(n / 2)
- 1。這種情況下,其執行時間的遞迴式為 t ( n ) <= 2 t ( n / 2 ) + θ ( n )。該遞迴式的解為 t ( n ) = o ( n lg n )。
隨機劃分使用隨機取樣(random sampling)的隨機化技術,從子陣列 a [ p .. r ]中隨機選擇乙個元素並與 a [ r ]互換,因為主元是隨機選擇的,我們期望在平均情況下,對輸入陣列的劃分能夠比較對稱。
randomized-partition(a, p, r)之前已經介紹了幾種能在 o ( n lg n )時間內排序 n 個數的演算法。比如歸併排序,堆排序和快速排序。這些演算法都有乙個相同的性質:排序結果中,各元素的次序基於輸入元素間的比較。這類排序演算法統稱為比較排序。1 i = random(p, r)
2 exchange a[r] with a[i]
3 return partition(a, p, r)
在乙個比較排序演算法中,僅用比較來確定輸入序列
, a2
, …, an
>的元素間次序。就是說,給定兩個元素 ai
和 aj
,測試 ai
, ai
<= aj
, ai
=aj, ai
>= aj
或 ai
> aj
中的哪乙個成立,以確定 ai
和 aj
之間的相對次序。
比較排序可以被抽象地視為決策樹。一棵決策樹是一棵滿二叉樹,表示某排序演算法作用於給定輸入所做的所有比較,而控制結構,資料移動等都被忽略了。下圖是插入排序作用於含三個元素的輸入序列上的決策樹。
在決策樹中,對每個內結點都註明 i : j ,其中1 <= i , j
<= n , n 是輸入序列中的元素個數。對每個葉結點都註明排列。排序演算法的執行對應於遍歷一條從樹根到葉結點的路徑。在每個內結點處都要做比較。當到達乙個葉結點是,排序演算法就確定了順序。要使排序演算法能正確地工作,其必要條件是, n 個元素的 n! 中排列中的每一種都要作為決策樹的乙個葉子出現
讀書筆記 演算法導論
第2章演算法入門 浮於表面不如深入其中,送給自己,自己是最大的敵人,那麼就盡最大努力去克服自己,沉思,冷靜,不浮躁!勘誤 在演算法導論第9頁,扼要的扼 內容提要 1 偽 的表示方法 2 插入排序演算法分析 3 迴圈不變式 4 演算法設計之分治法 divide and conquer 5 合併排序演算...
演算法導論讀書筆記(7)快速排序
與歸併排序一樣,也使用了分治思想 quick sort a,p,r if p r q partition a,p,r quick sort a,p,q 1 quick sort a,q 1,r 演算法的關鍵部分是partition過程,它實現了對子陣列a p.r 的原址重排。partition總是選...
演算法導論 讀書筆記2010 12 6
演算法就是一系列的計算步驟,用來將輸入資料轉換為輸出結果。資料結構師儲存和組織資料的一種方式,以便於對資料進行訪問和修改。插入排序演算法,對n個資料項的時間大約是c1n 2,其中c1是乙個不依賴於n的常量。亦即該演算法所需的時間大致與n 2成正比。合併排序演算法,排序n個資料項的時間大約是c2log...