快速排序是什麼?
利用分治法(divide and conquer)對數列做排序。基本原理:選一個基準值(pivot)(通常選第一/最後/中間或隨機一個),將數列分成兩部份,比基準值大的數列,與比基準值小的數列,後遞迴對這兩個部分做排序,最終合併已排序的部分得到最後結果。適合數據無特定條件與特性,或大量數據。
規則
由小至大排,從左至右>元素比基準值大,從右至左<比基準值小,做交換。如比基準值小的沒有,則是正確位置不用交換。
由大至小排,從左至右>元素比基準值小,從右至左<比基準值大,做交換。如比基準值大的沒有,則是正確位置不用交換。
* 記憶:左邊爸爸頭比較大,右邊兒子頭比較小
舉例
有一個數列[9, 3, 7, 6, 2, 8, 1, 5]用快速排序。
1. 選基準值5,分二數列[ 3, 2, 1|5|9,7,6,8]。
2. 對比基準值小數列[3,2,1],2當基準值的[1| 2|3]
3. 對比基準值大數列[9,7,6,8],8當基準值的[7,6| 8|9]
4. 對數列[7,6],6當基準值得,[6|7]
5. 合併所有數列得[1,2,3,5,6,7,8,9]
細節舉例(容易錯)
有一個數列[9, 3, 7, 6, 2, 8, 1, 5]用快速排序。下面為每回合(指基準值插入正確位置後算一個回合)步驟:
回合1. 選基準值為9,從兩邊找,左邊找比基準值大的沒有,右邊找比基準值小的5,左右代理人相遇在5,與基準值9交換
[|9|, 3, 7, 6, 2, 8, 1, 5]
[|5|, 3, 7, 6, 2, 8, 1, 9]
回合2. 選基準值5,從兩邊找,左邊找比基準值大的7,右邊找比基準值小的1,交換
[|5|, 3, 7, 6, 2, 8, 1, 9]
[|5|, 3, 1, 6, 2, 8, 7, 9]
(1). 選基準值5,從兩邊找,左邊找比基準值大的6,右邊找比基準值小的2,交換
[|5|, 3, 1, 6, 2, 8, 7, 9]
[|5|, 3, 1, 2, 6, 8, 7, 9]
(2). 左右代理人相遇在2與基準值5交換
[|5|, 3, 1, 2, 6, 8, 7, 9]
[|2|, 3, 1, 5, 6, 8, 7, 9]
(3) 選基準值2,從兩邊找,左邊找比基準值大的3,右邊找比基準值小的1,交換
[|2|, 1, 3, 5, 6, 8, 7, 9]
(4) 選基準值2,從兩邊找,左邊找比基準值大的3,右邊找比基準值小的1,相遇在1交換
[|1|, 2, 3, 5, 6, 8, 7, 9]
(5) 選基準值1,從兩邊找,左邊找比基準值大的2,右邊找比基準值小的沒有,在正確位置不換
[|1|, 2, 3, 5, 6, 8, 7, 9]
[1, |2|, 3, 5, 6, 8, 7, 9]
...
[1, 2, 3, 5, 6, |8|, 7, 9]
(5) 選基準值8,從兩邊找,左邊找比基準值大的9,右邊找比基準值小的7,相遇在7換
[1, 2, 3, 5, 6, |8|, 7, 9]
[1, 2, 3, 5, 6, |7|, 8, 9]
時間複雜度
最佳/平均時間複雜度,每次分割基準值的過程耗時log n,比較需耗時(O(n)),所以時間複雜度為O(nlogn)。
最差時間複雜度,每次選基準值在最大或最小值,造成分區不平衡,遞迴深度為n,每次分割皆掃描整個數列做分區(O(n)),所以時間複雜度O(n^2)。為避免最差,通常用隨機取基準值或三數(第一、最後、中間元素)取中間值法。
空間複雜度
快速排序的空間複雜度是平均情況下為 O(log n)。因快速排序是原地排序演算法(in-place sorting),主要使用遞迴實現,因此在遞迴過程中每次分割會佔用 O(log n) 的空間。
沒有留言:
張貼留言
寫下幸福點子吧!