面試官:快排會寫嗎?
阿新 • • 發佈:2018-11-14
快排可以說是一道必知的常見面試題,同時也有多種實現方式。在這篇文章中,我使用的是隨機三路快排。
之所以使用隨機快速排序而不是普通的快排。是因為前者可以使得數列有序的概率降低,從而使隨機快速排序平均速度是比快速排序要快的。具體的兩者的效能差別可以看下這篇文章:
talk id cheap,show the code。一共 20+ 行程式碼,每行程式碼都有註釋。其中交換陣列元素位置,列印元素的方法我就沒貼了,程式碼太長你們也不方便看。
PS:程式碼下面有執行流程圖,結合程式碼來看比較容易理解。
public static void main(String[] args) {
// 測試資料
int[] arr = new int[]{5, 3, 6, 4};
// 執行快排
quickSort(arr, 0, arr.length - 1);
// 列印陣列元素
print Array(arr);
}
private static void quickSort(int[] arr, int l, int r) {
if (l < r) {
// 隨機取需要排序的陣列中的一個元素和陣列的最後一個元素交換,作為劃分值
swap(arr, l + (int) (Math.random() * (r - l + 1)), r);
// 得到陣列元素中等於劃分值的區域
int[] part = partition(arr, l, r);
// 小於等於劃分值的區域
quickSort(arr, l, part[0] - 1);
// 大於劃分值的區域
quickSort(arr, part[1] + 1, r);
}
}
private static int[] partition(int[] arr, int l, int r) {
// 初始化小於等於劃分值區域的當前下標,預設是陣列第一個元素的前一個位置
int less = l - 1;
// 初始化大於劃分值區域的當前下標,預設是陣列最後一個元素的位置,同時也是劃分值的位置,但該值並不屬於大於劃分值的區域,所以要在最後進行移動
int more = r;
// 當前下標小於大於劃分值區域的下標時
while (l < more) {
// 當前值比劃分值小,當前值和小於等於劃分值區域的右邊第一個值進行交換,小於等於劃分值區域右移1個下標,當前下標+1
if (arr[l] < arr[r]) {
swap(arr, l++, ++less);
// 當前值比劃分值大,當前值和大於劃分值區域的左邊第一個值進行交換,大於劃分值的區域左移1個下標
} else if (arr[l] > arr[r]) {
swap(arr, l, --more);
// 當前值等於劃分值,當前下標+1
} else {
// 當前下標+1
l++;
}
}
// 將劃分值和大於劃分值區域中,最接近劃分值區域的元素交換。至此完成所有值的區域劃分
swap(arr, more, r);
// 返回等於劃分值的區域
return new int[]{less + 1, more};
}
複製程式碼
下面我會畫個流程圖幫大家理解一下,測試資料和程式碼一樣。
假設程式碼執行完 13 行後,測試資料的順序依舊不變,即為 {5,3,6,4}。
接下來在執行 partition() 方法的過程中,陣列元素的情況如下圖所示(靈魂寫手求輕噴)
好了,以上就是本文的全部內容,我們下篇文章再見,捂臉逃~
PS:本文原創釋出於微信公眾號「不只Java」,後臺回覆「Java」,送你 13 本 Java 經典電子書。公眾號專注分享 Java 乾貨、讀書筆記、成長思考