快速排列,又稱劃分交換排序,簡稱快排,一種排序算法。在平均狀況下,排序個項目要次比較。在最壞狀況下則需要次比較,但這次狀況並不常見。事實上,快速排序通常明顯比其他算法更快,因爲它的內部循環可以在大部分的架構上很有效率的達成。
算法
快速排序使用分治法策略來吧一個序列分爲較小和較大的兩個子序列,然後遞歸地排序兩個子序列。
步驟爲:
1.挑選基準值:從數組中挑出一個元素,稱爲“基準”,
2.分割:重新排序數列,所有比基準值小的元素擺放在基準前面,所有比基準值大的元素擺在基準後面(與基準值相等的數可以放到任何一邊)。在這個分割結束之後,對基準值的排序已經完成,
3.遞歸排序子序列:遞歸地將小於基準值元素的子序列和大於基準值元素的子序列。
遞歸到最底部的判斷條件是數列的大小是零或一,此時該數列顯然已經有序。
選取基準值有數種具體方法,次選取方法對排序的時間性能有決定性影響。
在簡單的僞代碼中,此算法可以被表示爲:
function quicksort(q)
{
var list less, pivotList, greater
if length(q) ≤ 1
return q
else
{
select a pivot value pivot from q
for each x in q except the pivot element
{
if x < pivot then add x to less
if x ≥ pivot then add x to greater
}
add pivot to pivotList
return concatenate(quicksort(less), pivotList, quicksort(greater))
}
}
原地(in-place)分割版本
上面簡單版本的缺點是,他需要的額外存儲空間,也就是跟歸併排序一樣不好。額外需要的存儲器空間配置,在實際上的實現,也會極度影響速度和緩存的性能。有一個比較複雜使用原地分割算法的版本,且在好的基準選擇上,平均可以達到空間的使用複雜度。
function partition(a, left, right, pivotIndex)
{
pivotValue = a[pivotIndex]
swap(a[pivotIndex], a[right]) // 把pivot移動到結尾
storeIndex = left
for i from left to right-1
{
if a[i] <= pivotValue
{
swap(a[storeIndex], a[i])
storeIndex = storeIndex + 1
}
}
swap(a[right], a[storeIndex]) // 把pivot移動到它最後的地方
return storeIndex
}
這裏原地分割算法,它分割了標示爲left和right的序列部分,藉由移動小於a[pivotIndex]的所有元素到子序列的開頭,留下大於或者等於的元素接在它們後面。在這個過程它也可爲基準元素找尋最後擺放的位置,也就是它回傳的值。它暫時地把基準元素移到子序列的結尾,而不會被前述方式影響到。由於算法只是用交換,因此最後的數列與原先的數列擁有一樣的元素。要注意的是,一個元素在到達它的最後位置前,可能會被交換很多次。
一旦我們有了這個分割算法,要寫快速排序本身就很容易了:
procedure quicksort(a, left, right)
if right > left
select a pivot value a[pivotIndex]
pivotNewIndex := partition(a, left, right, pivotIndex)
quicksort(a, left, pivotNewIndex-1)
quicksort(a, pivotNewIndex+1, right)
維基百科:快速排序