思路:
快速排序的本質就是選取一個基準數,通過一次快排把基準數大的都放在基準數的左邊,把比基準數小的放在基準數的右邊,這樣就找到了基準數在數組中的正確位置。
然後可以用遞歸的方式分別對前半部分和後半部分排序,最終實現整體數組有序。
快排是不是穩定排序?
所謂排序的穩定性,就是指在排序過程中,在對某關鍵字排序後會不會改變其他關鍵字的順序。快排會改變,所以不是穩定排序。
代碼:
常規代碼1:
def AdjustPartition(list1,low,high):
if low < high:
left = low
right = high
key = list1[left]
while left < right:
while left < right and list1[right] >= key:
right = right - 1
list1[left] = list1[right]
while left < right and list1[left] <= key:
left = left + 1
list1[right] = list1[left]
list1[left] = key
AdjustPartition(list1,low,left-1)
AdjustPartition(list1,left+1,high)
return list1
常規代碼2:
def quick_sort(arr):
if len(arr) < 2:
return arr
key = arr[0] # 以第一個關鍵字作爲基準數
left, right = [], []
arr.remove(key)
for item in arr:
if item >= key:
right.append(item)
else:
left.append(item)
return quick_sort(left) + [key] + quick_sort(right)
python一行代碼實現快排:
def quick_sort(a):
if len(a) > 1:
return quick_sort([i for i in a[1:] if i <= a[0]]) + [a[0]] + quick_sort([i for i in a[1:] if i > a[0]])
else:
return a
轉化爲一行:
quick_sort = lambda a:a if len(a) <= 1 else quick_sort([i for i in a[1:] if i <= a[0]]) + \
[a[0]] + quick_sort([i for i in a[1:] if i > a[0]])
快排優化
如果數組元素是隨機的,那麼程序的運行時間不會有太大的波動。如果數組元素已經基本有序時,此時的固定基準劃分就容易產生最壞的情況,即快速排序變成冒泡排序,時間複雜度爲O()。
eg: 序列1 2 3 6 12 18,如果用固定基準進行快排:(【】內爲基準數)
第一趟:【1 】2 3 6 12 18
第二趟:1【 2】 3 6 12 18
第三趟:1 2 【3】 6 12 18
第四趟:1 2 3 【6】 12 18
第四趟:1 2 3 6 【12】 18
快排基準的選擇:
(1)固定基準
比如每次以第一個關鍵字作爲基準數。可能會退化爲冒泡排序。
(2)隨機基準
可以利用隨機函數隨機生成在[low,high]範圍內的數作爲基準數的下標。
(3)三數取中
隨機基準選取的隨機性,因此即使是同一個數組每次效率也是不一樣的,此時可以選擇三數取中的方法選取基準數。它的思路是:選取數組開頭,中間和結尾的元素去比較,選擇中間的值作爲快排的基準。這種方式既能解決待排數組基本有序的情況,而且選取的基準也不是隨機的。
eg:序列1 2 3 6 12 18,30,如果用三數取中進行快排:
因爲:
數組開頭是1,中間是6,結尾是30
所以:
所以基準數選擇6進行快排。
快排優化方案
- 在數組長度大於某一個閾值範圍時,使用遞歸快排,當數據長度小於閾值時,使用插入排序。因爲處理較短序列時插入排序效果更好。
- 在partition中選取基準數時,選取三路取中。
- 進行三路快排優化。即將數組劃分爲左邊小於基準數,中間等於基準數,右邊大於基準數,這樣兩端遞歸時可以縮小遞歸數組的大小。