1. 程式人生 > >6.5 快速排序

6.5 快速排序

quick bubuko 意思 大小 個數 while 運算 通過 clas

(1)快速排序:

  快速排序(英語:Quicksort),又稱劃分交換排序(partition-exchange sort),通過一趟排序將要排序的數據分割成獨立的兩部分,其中一部分的所有數據都比另外一部分的所有數據都要小,然後再按此方法對這兩部分數據分別進行快速排序,整個排序過程可以遞歸進行,以此達到整個數據變成有序序列。

  步驟為:    

    1.從數列中挑出一個元素,稱為"基準"(pivot),

    2.重新排序數列,所有元素比基準值小的擺放在基準前面,所有元素比基準值大的擺在基準的後面(相同的數可以到任一邊)。在這個分區結束之後,該基準就處於數列的中間位置。這個稱為分區(partition)操作。

    3.遞歸地(recursive)把小於基準值元素的子數列和大於基準值元素的子數列排序。

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

(2)快速排序的分析:

  技術分享圖片

(3)代碼實現:

  

 1 def quick_sort(alist, first, last):
 2     """快速排序"""
 3     if first >= last:   # 總體遞歸結束條件
 4         return
 5     mid = alist[first]
6 low = first 7 high = last 8 while low < high: 9 # high遊標左移 10 while low < high and alist[high] >= mid: # 註意並列的兩個while只有一個有=號,才能保證相同的元素在同一邊 11 high -= 1 12 alist[low] = alist[high] 13 14 # low遊標右移 15 while low < high and
alist[low] < mid: 16 low += 1 17 alist[high] = alist[low] 18 # 從循環退出時,low==high 19 alist[low] = mid # <==>alist[high] = mid 20 21 # 對low左邊的列表執行快速排序 22 quick_sort(alist, first, low-1) # quick_sort(alist[:low-1]) 23 24 # 對low右邊的列表執行快速排序 25 quick_sort(alist, low+1, last) # quick_sort(alist[low+1:]) 26 27 28 if __name__ == "__main__": 29 li = [54, 26, 93, 17, 77, 31, 44, 55, 20] 30 print(li) 31 quick_sort(li, 0, len(li)-1) 32 print(li)

(4)運行結果:

  技術分享圖片

(5)時間復雜度:

    最優時間復雜度:O(n log n)

    最壞時間復雜度:O(n2)

    穩定性:不穩定

  從一開始快速排序平均需要花費O(n log n)時間的描述並不明顯。但是不難觀察到的是分區運算,數組的元素都會在每次循環中走訪過一次,使用O(n)的時間。在使用結合(concatenation)的版本中,這項運算也是O(n)。

  在最好的情況,每次我們運行一次分區,我們會把一個數列分為兩個幾近相等的片段。這個意思就是每次遞歸調用處理一半大小的數列。因此,在到達大小為一的數列前,我們只要作 log n 次嵌套的調用。這個意思就是調用樹的深度是O(log n)。但是在同一層次結構的兩個程序調用中,不會處理到原來數列的相同部分;因此,程序調用的每一層次結構總共全部僅需要O(n)的時間(每個調用有某些共同的額外耗費,但是因為在每一層次結構僅僅只有O(n)個調用,這些被歸納在O(n)系數中)。結果是這個算法僅需使用O(n log n)時間。

(6)快速排序演示:

  技術分享圖片

6.5 快速排序