java實現歸併排序

基本思想

歸併排序(MERGE-SORT)是利用歸併的思想實現的排序方法,該算法採用經典的分治(divide-and-conquer)策略(分治法將問題(divide)成一些小的問題然後遞歸求解,而治(conquer)的階段則將分的階段得到的各答案"修補"在一起,即分而治之)。

分而治之

 可以看到這種結構很像一棵完全二叉樹,本文的歸併排序我們採用遞歸去實現(也可採用迭代的方式去實現)。階段可以理解爲就是遞歸拆分子序列的過程,遞歸深度爲log2n。

合併相鄰有序子序列

再來看看階段,我們需要將兩個已經有序的子序列合併成一個有序序列,比如上圖中的最後一次合併,要將[4,5,7,8]和[1,2,3,6]兩個已經有序的子序列,合併爲最終序列[1,2,3,4,5,6,7,8],來看下實現步驟。

代碼實現 

public class MergeSort {

    public static void main(String[] args) {
        int[] arr = { 8, 4, 5, 7, 1, 3, 6, 2 };
        int[] temp = new int[arr.length];
        mergeSort(arr,0,arr.length - 1,temp);
        System.out.println(Arrays.toString(arr));
    }

    //先分解後合併
    public static void mergeSort(int[] arr, int left, int right, int[] temp ){
        if(left < right){
            int mid = (left + right) / 2;
            //向左遞歸分解
            mergeSort(arr, left, mid, temp);
            //向右遞歸分解
            mergeSort(arr,mid + 1, right, temp);
            //合併
            merge(arr, left, mid, right, temp);
        }
    }

    /**
     * 合併方法
     * @param arr 排序的原始數組
     * @param left 左邊有序序列的初始指針
     * @param mid 中間指針
     * @param right 右邊指針
     * @param temp 做中轉的數組
     */
    public static void merge(int[] arr , int left ,int mid, int right, int[] temp){
        int i = left;//初始化i 左邊有序序列的初始指針
        int j = mid + 1;//初始化j 右邊有序序列的初始指針
        int t = 0;//指向temp當前指針
        /**
         * 第一步:先把左右兩邊(有序)的數據按照規則填充到temp數組,
         * 直到左右兩邊序列,有一邊處理完畢爲止
         */
        while (i <= mid && j <= right){
            /**
             * 如果左邊的有序序列當前元素,小於等於右邊有序當前元素
             * 即將左邊的數拷貝到temp數組中,左邊序列指針向前移動一下,
             * temp指針向前移動一下
             */
            if(arr[i] <= arr[j]){
                temp[t] = arr[i];
                t++;
                i++;
            }else{//反之
                temp[t] = arr[j];
                t++;
                j++;
            }
        }
        /**
         * 第二步:如果能走到這一步,說明上一個while循環條件中必定有一個條件爲false,
         * 條件爲false,說明左右序列中有一個序列已經執行完畢,
         * 所以把有剩餘數據的一邊的數據依次填充到temp中
         */
        while(i <= mid){//左邊序列有剩餘數據
            temp[t] = arr[i];
            t++;
            i++;
        }
        while(j <= right){//右邊序列有剩餘數據
            temp[t] = arr[j];
            t++;
            j++;
        }
        /**
         * 第三步:將temp數組中的元素拷貝到arr數組中
         */
        t = 0;
        int tempLeft = left;
        while(tempLeft <= right){
            arr[tempLeft] = temp[t];
            t++;
            tempLeft++;
        }
    }
}

運行結果

以上畫圖思想參考:https://www.cnblogs.com/chengxiao/p/6194356.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章