1.概念
快速排序,聽這個名字就能想到它排序速度比較快方法,是一種分治思想,現在各種語言中自帶的排序庫很多使用的都是快速排序。
空間復雜度
快速排序是一種原地排序,只需要一個很小的棧作為輔助空間,空間復雜度為O(log2n),所以適合在數據集比較大的時候使用。
時間復雜度
時間復雜度比較復雜,最好的情況是O(n),最差的情況是O(n2),所以平時說的O(nlogn),為其平均時間復雜度。
2.基本思想
隨機找出一個數,可以隨機取,也可以取固定位置,一般是取第一個或最后一個稱為基准,然后就是比基准小的在左邊,比基准大的放到右邊,如何放做,就是和基准進行交換,這樣交換完左邊都是比基准小的,右邊都是比較基准大的,這樣就將一個數組分成了兩個子數組,然后再按照同樣的方法把子數組再分成更小的子數組,直到不能分解為止。
3.舉例說明
方法其實很簡單,
1.分別從初始序列“6 1 2 7 9 3 4 5 10 8”兩端開始“探測”。先從右往左找一個小於6的數,再從左往右找一個大於6的數,然后交換他們。這里可以用兩個變量i和j,分別指向序列最左邊和最右邊。我們為這兩個變量起個好聽的名字“哨兵i”和“哨兵j”。剛開始的時候讓哨兵i指向序列的最左邊(即i=1),指向數字6。讓哨兵j指向序列的最右邊(即j=10),指向數字8。

首先哨兵j開始出動。因為此處設置的基准數是最左邊的數,所以需要讓哨兵j先出動,這一點非常重要(請自己想一想為什么)。哨兵j一步一步地向左挪動(即j--),直到找到一個小於6的數停下來。
2.接下來哨兵i再一步一步向右挪動(即i++),直到找到一個數大於6的數停下來。最后哨兵j停在了數字5面前,哨兵i停在了數字7面前。


現在交換哨兵i和哨兵j所指向的元素的值。交換之后的序列如下。





1 #快速排序 傳入列表、開始位置和結束位置 2 def quick_sort( li , start , end ): 3 # 如果start和end碰頭了,說明要我排的這個子數列就剩下一個數了,就不用排序了 4 if not start < end : 5 return 6 7 mid = li[start] #拿出第一個數當作基准數mid 8 low = start #low來標記左側從基准數始找比mid大的數的位置 9 high = end #high來標記右側end向左找比mid小的數的位置 10 11 # 我們要進行循環,只要low和high沒有碰頭就一直進行,當low和high相等說明碰頭了 12 while low < high : 13 #從high開始向左,找到第一個比mid小或者等於mid的數,標記位置,(如果high的數比mid大,我們就左移high) 14 # 並且我們要確定找到之前,如果low和high碰頭了,也不找了 15 while low < high and li[high] > mid : 16 high -= 1 17 #跳出while后,high所在的下標就是找到的右側比mid小的數 18 #把找到的數放到左側的空位 low 標記了這個空位 19 li[low] = li[high] 20 # 從low開始向右,找到第一個比mid大的數,標記位置,(如果low的數小於等於mid,我們就右移low) 21 # 並且我們要確定找到之前,如果low和high碰頭了,也不找了 22 while low < high and li[low] <= mid : 23 low += 1 24 #跳出while循環后low所在的下標就是左側比mid大的數所在位置 25 # 我們把找到的數放在右側空位上,high標記了這個空位 26 li[high] = li[low] 27 #以上我們完成了一次 從右側找到一個小數移到左側,從左側找到一個大數移動到右側 28 #當這個while跳出來之后相當於low和high碰頭了,我們把mid所在位置放在這個空位 29 li[low] = mid 30 #這個時候mid左側看的數都比mid小,mid右側的數都比mid大 31 32 #然后我們對mid左側所有數進行上述的排序 33 quick_sort( li , start, low-1 ) 34 #我們mid右側所有數進行上述排序 35 quick_sort( li , low +1 , end ) 36 37 38 #ok我們實踐一下 39 if __name__ == '__main__': 40 li = [5,4,3,2,1] 41 quick_sort(li , 0 , len(li) -1 ) 42 print(li)
4. 算法分析
優點:速度快,剩空間,缺點:非常脆弱,在實現時一定要注意幾個小細節。
什么情況下是最好的呢:
待排序列升序有序O(n),即,1 2 3 4 5 6 7,這種情況下,基准選擇第一個數,調整次數最少,注意只是調試次數減少,比較次數沒變少,
所以從理論上來說,比較只需要把數據放入寄存器,然后比較。
mov ax,
mov cx,
cmp ax,cx
但實際情況下,因為有L1,L2的存在,然后你的程序又存在進程切換,現場恢復等等各種復雜因素,實際上的速度就好說了。
什么情況下是最差的呢:
待排序序列降序有序O(n2),即,7 6 5 4 3 2 1,這種情況就退化為冒泡排序。
5.瞎逼逼
快速排序,在排完第一遍的時候,你所選擇的基准數就是該數在排序序列中的真實位置。
所以可以瞎想一下,如果基准選擇准確,是否可以幾次遍歷就求出一個無序序列的中位數呢???
轉載請注明——redbear博客