面試題51——歸併排序的一個優化(想的時間有點久)
阿新 • • 發佈:2021-07-12
排序演算法之——歸併排序(兩種方法及其優化)(關於演算法的實現具體看連結)
本文將圍繞程式碼從多個方面分析歸併演算法,歸併的操作很簡單,稍加思考便能深刻理解。重點理解第三個優化的實現,其實就是在merge裡少了一步複製,如果只是傳入一個原陣列,需要將原陣列複製到輔助陣列。然後再通過輔助陣列歸併排序。
而如果傳入了兩個陣列,其中的一個數組的子陣列已經排好序了,就可以直接歸併了,不需要複製。
這需要通過技巧,如果sort函式的形參是(A,AUX),則每次遞迴時sort函式實參應該傳入(AUX,A)(sort函式中的merge函式的實參為(A,AUX))
優化後的merge函式,注意第一個for迴圈已經被註釋掉了
public static void merge(Comparable[] a, Comparable[] aux, int lo, int mid, int hi) {// 原地歸併的抽象方法 int i = lo, j = mid + 1; // for (int k = lo; k <= hi; k++) { // aux[k] = a[k]; // } for (int k = lo; k <= hi; k++) { if (i > mid) { a[k] = aux[j++]; } else if (j > hi) { a[k] = aux[i++]; } else if (less(aux[j], aux[i])) { a[k] = aux[j++]; } else { a[k] = aux[i++]; } } }
優化後的sort函式,注意裡面還有書上提到的其餘兩個優化,注意實參形參的使用。
private static void sort(Comparable[] a, Comparable[] aux, int lo, int hi) { /* * 自頂向下的並歸排序 三個改進 */ // if (hi <= lo) { // return; // } int mid = lo + (hi - lo) / 2; if (hi - lo <= 7) {// 對小規模子陣列使用插入排序 //System.out.println("insert!"); insertionSort(a, lo, hi); return; } sort(aux, a, lo, mid); sort(aux, a, mid + 1, hi); if (!less(aux[mid + 1], aux[mid])) {// 已經有序時跳過merge(a中lo到mid mid到hi分別都是有序的) System.arraycopy(aux, lo, a, lo, hi-lo+1); return; } merge(a, aux, lo, mid, hi); }