1. 程式人生 > 其它 >面試題51——歸併排序的一個優化(想的時間有點久)

面試題51——歸併排序的一個優化(想的時間有點久)

排序演算法之——歸併排序(兩種方法及其優化)(關於演算法的實現具體看連結)

本文將圍繞程式碼從多個方面分析歸併演算法,歸併的操作很簡單,稍加思考便能深刻理解。重點理解第三個優化的實現,其實就是在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);
     }