6.5 快速排序
(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 andalist[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 快速排序