歸并排序

分類 -------------- 內(nèi)部比較排序
數(shù)據(jù)結(jié)構(gòu) ---------- 數(shù)組
最差時間復(fù)雜度 ---- O(nlogn)
最優(yōu)時間復(fù)雜度 ---- O(nlogn)
平均時間復(fù)雜度 ---- O(nlogn)
所需輔助空間 ------ O(n)
穩(wěn)定性 ------------ 穩(wěn)定

原理

???????歸并排序的實現(xiàn)分為遞歸實現(xiàn)與非遞歸(迭代)實現(xiàn)。遞歸實現(xiàn)的歸并排序是算法設(shè)計中分治策略的典型應(yīng)用,我們將一個大問題分割成小問題分別解決,然后用所有小問題的答案來解決整個大問題。非遞歸(迭代)實現(xiàn)的歸并排序首先進(jìn)行是兩兩歸并,然后四四歸并,然后是八八歸并,一直下去直到歸并了整個數(shù)組。

步驟

  1. 申請空間,使其大小為兩個已經(jīng)排序序列之和,該空間用來存放合并后的序列
  2. 設(shè)定兩個指針,最初位置分別為兩個已經(jīng)排序序列的起始位置
  3. 比較兩個指針?biāo)赶虻脑?,選擇相對小的元素放入到合并空間,并移動指針到下一位置
  4. 重復(fù)步驟3直到某一指針到達(dá)序列尾
  5. 將另一序列剩下的所有元素直接復(fù)制到合并序列尾

代碼實現(xiàn)

public class MergeSort {

    // 合并兩個已排好序的數(shù)組A[left...mid]和A[mid+1...right]
    void merge(Integer a[], int left, int mid, int right)
    {
        int len = right - left + 1;
        // 輔助空間O(n)
        Integer[] temp = new Integer[len];
        int index = 0;
        // 前一數(shù)組的起始元素
        int i = left;
        // 后一數(shù)組的起始元素
        int j = mid + 1;
        while (i <= mid && j <= right)
        {
            // 帶等號保證歸并排序的穩(wěn)定性
            temp[index++] = a[i] <= a[j] ? a[i++] : a[j++];
        }
        while (i <= mid)
        {
            temp[index++] = a[i++];
        }
        while (j <= right)
        {
            temp[index++] = a[j++];
        }
        for (int k = 0; k < len; k++)
        {
            a[left++] = temp[k];
        }
    }
    // 遞歸實現(xiàn)的歸并排序(自頂向下)
    void mergeSortRecursion(Integer a[], int left, int right)
    {
        // 當(dāng)待排序的序列長度為1時,遞歸開始回溯,進(jìn)行merge操作
        if (left == right)
        {
            return;
        }
        int mid = (left + right) / 2;
        mergeSortRecursion(a, left, mid);
        mergeSortRecursion(a, mid + 1, right);
        merge(a, left, mid, right);
    }

    // 非遞歸(迭代)實現(xiàn)的歸并排序(自底向上)
    void mergeSortIteration(Integer a[], int len)
    {
        // 子數(shù)組索引,前一個為A[left...mid],后一個子數(shù)組為A[mid+1...right]
        int left, mid, right;
        // 子數(shù)組的大小i初始為1,每輪翻倍
        for (int i = 1; i < len; i *= 2)
        {
            left = 0;
            // 后一個子數(shù)組存在(需要歸并)
            while (left + i < len)
            {
                mid = left + i - 1;
                // 后一個子數(shù)組大小可能不夠
                right = mid + i < len ? mid + i : len - 1;
                merge(a, left, mid, right);
                // 前一個子數(shù)組索引向后移動
                left = right + 1;
            }
        }
    }

    public static void main(String[] args){
        Integer[] a = {3,4,1,9,5,2,6,10,20,16,13,11,0};
        Integer[] b = {3,4,1,9,5,2,6,10,20,16,13,11,0};

        MergeSort sort = new MergeSort();
        // 遞歸實現(xiàn)
        sort.mergeSortRecursion(a, 0, a.length - 1);
        // 非遞歸實現(xiàn)
        sort.mergeSortIteration(b, b.length);

        System.out.println("a by MergeSort is " + Tool.arrayToString(a));
        System.out.println("b by MergeSort is " + Tool.arrayToString(b));

    }
}

public class Tool {
    public static <T> String arrayToString(T[] array){
        StringBuilder builder = new StringBuilder("[");
        for (int i = 0; i < array.length; i++){
            T item = array[i];
            builder.append(item + "");
            if (i != array.length - 1){
                builder.append(",");
            }
        }

        builder.append("]");
        return builder.toString();
    }

    public static <T> void exchange(T[] array, int i, int j){
        T temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }
}

實現(xiàn)結(jié)果:

a by MergeSort is [0,1,2,3,4,5,6,9,10,11,13,16,20]
b by MergeSort is [0,1,2,3,4,5,6,9,10,11,13,16,20]
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • < 排序大全系列 > 歸并排序總結(jié): 導(dǎo)言: 在學(xué)習(xí)排序算法之前,我?guī)缀跛械呐判蛩惴ㄓ玫亩际恰懊芭菖判蚍ā?,?dāng)...
    路萬奇與青川君閱讀 1,026評論 0 0
  • 數(shù)據(jù)結(jié)構(gòu)與算法 1. 概述 我們總是可以將一個數(shù)組一分為二,然后二分為四,直到每一組只有兩個元素,這可以理解為個遞...
    凱玲之戀閱讀 550評論 0 0
  • 歸并排序 所謂歸并,就是將兩個或兩個以上的有序表合并成一個新的有序表。如下圖所示,有兩個已經(jīng)排好序的有序表A[1]...
    JackChen1024閱讀 2,474評論 0 4
  • 面試 11:Java 玩轉(zhuǎn)歸并排序 前面講了冒泡、選擇、插入三種簡單排序,時間復(fù)雜度都是 O(n2),今天,我們終...
    nanchen2251閱讀 1,336評論 1 11
  • 這幾天在自駕,途經(jīng)安徽地界。安徽的高速收費(fèi)有它的服務(wù)標(biāo)準(zhǔn)。當(dāng)車輛行駛到收費(fèi)口的時候,收費(fèi)人員要90度轉(zhuǎn)身,然后...
    穆珊珊閱讀 266評論 1 3

友情鏈接更多精彩內(nèi)容