分分鐘掌握快速排序

發表於2019-05-11
今天我們來學習一種不浪費空間、效率還非常高的排序演算法——快速排序。
演算法思想
快速排序的基本思想——分治法。
1. 選取基準數(pivot):選陣列中的第一個或者中間一個。
2. 分割槽:將陣列中比基準數小的放的左邊,比基準數大的放到右邊。
3. 遞迴:對左右分割槽重複1、2操作。
過程描述
有這樣一個陣列arr,長度為11。
13, 34, 23, 8, 12, 17, 12, 42, 4, 9, 19
1)  以第一個數13為基數。我們指定兩個變數i(i=0)、j(j=10)分別指向陣列兩端。我們將第一個數賦給pivot,pivot = arr。這時需要找一個比pivot小的數填充arr
[Nil], 34, 23, 8, 12, 17, 12, 42, 4, 9, 19            pivot = 13 (i=0,j=10)
2)  首先移動j,從右向左移動,直到找到第一個比pivot小的數。當j=9時,arr[j] < pivot,將arr[j]賦值給arr。此時有需要找一個大於或等於pivot的數,來填充arr[j]。
9, 34, 23, 8, 12, 17, 12, 42, 4, [Nil], 19            pivot = 13  (i=0, j=9)
3)  從左向右移動i,直到找到第一個大於等於pivot的數。當i=1時,arr > pivot,將arr賦值給arr[j]。再找一個比pivot小的數來填充arr
9, [Nil], 23, 8, 12, 17, 12, 42, 4, 34, 19            pivot = 13 (i=1, j=9)
4)  按照這個規律一直推下去直到i==j。就將pivot賦給arr(或者arr[j])。
9,4,23,8,12,17,12,42,[Nil],34,19            pivot = 13 (i=1, j=8)
9,4,[Nil],8,12,17,12,42,23,34,19            pivot = 13 (i=2, j=8)
9,4,12,8,12,17,[Nil],42,23,34,19            pivot = 13 (i=2, j=6)
9,4,12,8,12,[Nil],17,42,23,34,19            pivot = 13 (i=5, j=6)
第一次迴圈的結果是9, 4, 12, 8, 12, 13, 17, 42, 23, 34, 19。pivot(13)將陣列分成了左右兩個分割槽。
5) 利用遞迴的方式,對左右兩個分割槽做上述操作。
程式碼實現
先看Java程式碼實現,結合上面的過程描述以及程式碼裡面的註釋,相信不難看明白。
?
1
2
3
4
public static void quickSort(int arr[], int start, int end) {    if(start < end) { int pivot = arr[start]; int i = start, j = end;while(i < j) {// 從右向左移動j,直到找到第一個小於pivot的數 while(i < j && arr[j] >= pivot)                j--;             if(i < j) arr[i++] = arr[j];// 從左向右移動i,直到找到第一個大於等於pivot的數 while(i < j && arr < pivot) i++; if(i < j) arr[j--] = arr; } // 直到i == j,遍歷結束,將pivot賦給arr arr = pivot; // 遞迴呼叫 quickSort(arr, start, i - 1); quickSort(arr, i + 1, end); } }

再看用Scala如何實現
?
1
2
3
4
def sortScala(xs: Array[Int]): Array[Int] = {   if(xs.length <= 1) xselse{ val pivot = xs(xs.length / 2) Array.concat( sortScala(xs filter (pivot >)),         xs filter (pivot ==),         sortScala(xs filter (pivot <))) } }

哇哦,簡潔程度簡直亮瞎雙眼。只不過與我們前面描述過程稍微有些差別。這裡是將分割槽分成大於、小於、等於三部分,每次都對遞迴結果做個合併就OK了,缺點就是它需要更多的轉換空間。
如果你想了解scala,可以參照我的另一篇部落格Scala極速入門
總結
快速排序是基於分治法、不穩定的排序演算法。時間複雜度平均情況為O(n*logn),最差情況為O(n^2)。
原文點此檢視
回覆

相關文章