1. 程式人生 > >常見排序演算法之歸併排序

常見排序演算法之歸併排序

文章目錄

常見排序演算法之歸併排序

原地歸併方法

該方法將兩個不同的有序陣列歸併到第三個陣列中。

    private static void merge(Comparable[] a, Comparable[] aux, int lo, int mid, int hi) {
        // copy to aux[]
        for (int k =
lo; k <= hi; k++) { aux[k] = a[k]; } // merge back to a[] int i = lo, j = mid+1; 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++]; } }

自頂向下的歸併排序

自頂向下的歸併排序應用了分治的思想,要對子陣列a[lo…hi]進行排序,先將它分為a[lo…mid]和a[mid+1…hi]兩部分,分別通過遞迴呼叫將它們單獨排序,最後將有序的子陣列歸併為最終的排序結果。

自頂向下的歸併排序

圖為自頂向下的歸併排序中歸併結果的軌跡

public class Merge {
    public static
void sort(Comparable[] a) { Comparable[] aux = new Comparable[a.length]; sort(a, aux, 0, a.length-1); } private static void sort(Comparable[] a, Comparable[] aux, int lo, int hi) { if (hi <= lo) return; int mid = lo + (hi - lo) / 2; sort(a, aux, lo, mid); sort(a, aux, mid + 1, hi); merge(a, aux, lo, mid, hi); } }

自底向上的歸併排序

實現歸併排序的另一種方法是先歸併那些微型陣列,然後再成對歸併得到子陣列,如此這般地多次遍歷整個陣列,直到我們將整個陣列歸併到一起。

自底向上的歸併排序

圖為自底向上的歸併排序中歸併結果的軌跡

public class MergeBU {
    public static void sort(Comparable[] a) {
        int n = a.length;
        Comparable[] aux = new Comparable[n];
        for (int len = 1; len < n; len *= 2) {
            for (int lo = 0; lo < n-len; lo += len+len) {
                int mid  = lo+len-1;
                int hi = Math.min(lo+len+len-1, n-1);
                merge(a, aux, lo, mid, hi);
            }
        }
    }
}

特點

  • 歸併排序的空間複雜度不是最優的
  • 和選擇排序一樣,排序的效能不受輸入資料的影響,但表現比選擇排序好的多

複雜度分析

  • 最壞情況時間複雜度 O(nlogn)
  • 最好情況時間複雜度 O(nlogn)
  • 平均情況時間複雜度 O(nlogn)
  • 空間複雜度 O(n)
  • 穩定

參考資料