前言
一般的Quick Sort 都是做 2-way partition,不斷的把資料根據 pivot 位置,切割成兩邊,但在資料有很多相同數值時,效率會下降
因為切割成兩邊是指 >pivot
與 <=pivot
或是 >=pivot
與 <pivot
的情況,並沒有嚴格定義當 =pivot
的情況發生時應該怎麼做,所以當有很多一樣的數值出現在陣列中,就會發現做了一些不必要的交換而降低速度
3-way Quick sort 平均時間複雜度為 $O(NlogN)$,一樣屬於 unstable sorting
概念
Dijkstra 提出了新的演算法,從 2-way partition 變成 3-way partition
可以到 Toptal 的這個網頁觀看不同 case 的視覺化排序過程
將範圍嚴格定義成 <pivot
、=pivot
、>pivot
,就能以原有的效率處理 special case
把小於pivot的數值往左堆,大於pivot的數值往右堆,一樣的數值都擺在中間不要動到,就能避免發生不必要的交換了
做完往左堆和往右堆後,會紀錄兩個index回傳,而不是回傳 pivot 的最終位置
這兩個 index,一個是 lt
(less than),另一個是 gt
(greater than),而介於 lt 與 gt 之間的就是一樣的數值
想法上看起來是容易理解,網路上也有不少資料說明,可是真正在實作程式時卻有一點眉眉角角要注意
lt和gt之間的那一塊並不會丟進去做遞迴(就是一樣的數值),每次做遞迴的只有 < lt 與 > gt 那兩塊陣列
大致的想法圖如下 (有點簡陋XD,修圖時不小心蓋到 i--
和 gt--
)
pivot 一樣都是選在陣列最左邊,只是分堆的判定少了等於,需要非常注意的是 lt 跟 gt 的位置
pseudo code
1 | QuickSort(A[1..n], left, right) |
1 | Partition2(A[1..n], left, right) |
複雜度比較
大致上與 2-way Quick sort 一樣,差別在於情況如果只有 $O(1)$ 獨立數值,時間複雜度可達到 $O(N)$