快速排序(Quick Sort)

[簡介]算法

  快速排序英語:Quicksort),又稱劃分交換排序(partition-exchange sort),最先由東尼·霍爾提出。在平均情況下,排序n個項目要Ο(n log n)次比較。在最壞情況下則須要Ο(n2)次比較,但這種情況並不常見。事實上,快速排序一般明顯比其餘Ο(n log n)算法更快,由於它的內部循環(inner loop)能夠在大部分的架構上頗有效率地被實現出來。架構

 

[算法複雜度]ide

  僅針對非原地版本進行討論oop

  

  非原地版本的快速排序,在它的任何遞歸調用前須要使用O(n)空間。在最好的狀況下,它的空間仍然限制在O(n),由於遞歸的每一階中,使用與上一次所使用最多空間的一半,且ui

\sum _{i=0}^{\infty }{\frac {n}{2^{i}}}=2n

  它的最壞狀況是很恐怖的,須要spa

\sum _{i=0}^{n}(n-i+1)=\Theta (n^{2})

  空間,遠比數列自己還多。若是這些數列元素自己本身不是固定的大小,這個問題會變得更大;舉例來講,若是數列元素的大部分都是不一樣的,每個將會須要大約O(log n)爲原來存儲,致使最好狀況是O(n log n)和最壞狀況是O(n2 log n)的空間需求。code

 

[核心算法]xml

  

  快速排序使用分治法(Divide and conquer)策略來把一個序列(list)分爲兩個子序列(sub-lists)。blog

  步驟爲:排序

  1. 從數列中挑出一個元素,稱爲"基準"(pivot),
  2. 從新排序數列,全部元素比基準值小的擺放在基準前面,全部元素比基準值大的擺在基準的後面(相同的數能夠到任一邊)。在這個分區結束以後,該基準就處於數列的中間位置。這個稱爲分區(partition)操做。
  3. 遞歸地(recursive)把小於基準值元素的子數列和大於基準值元素的子數列排序。

  遞歸的最底部情形,是數列的大小是零或一,也就是永遠都已經被排序好了。雖然一直遞歸下去,可是這個算法總會結束,由於在每次的迭代(iteration)中,它至少會把一個元素擺到它最後的位置去。

 

 [Source Code]

def quick_sort(alist=None):
    blist = alist[:]
    N = len(blist)
    if N <= 1:
        return blist
    pivot = blist[0]
    return quick_sort([x for x in blist[1:] if x < pivot]) + [pivot] + quick_sort([x for x in blist[1:] if x >= pivot])

 

[示意圖]

相關文章
相關標籤/搜索