歸併排序(合併排序)Java

歸併排序(合併排序)Java

歸併排序

今天帶來的依舊是算法作業系列之🐢病排序(🐢:???)
在這裏插入圖片描述

哦說錯了,是歸併排序,我們老師的課件上也叫合併排序,下面是某度的百科的定義。

定義

歸併排序(MERGE-SORT)是建立在歸併操作上的一種有效的排序算法,該算法是採用分治法(Divide and Conquer)的一個非常典型的應用。將已有序的子序列合併,得到完全有序的序列;即先使每個子序列有序,再使子序列段間有序。若將兩個有序表合併成一個有序表,稱爲二路歸併。歸併排序是一種穩定的排序方法。

既然建立在歸併操作上,那麼什麼是🐢病操作呢?
在這裏插入圖片描述

將兩個順序序列合併成一個順序序列的方法。這就是歸併操作了。

分析

既然歸併操作是講兩個順序序列合併成一個順序序列,那麼也就是說,歸併排序其實也就是通過不斷的進行歸併操作,使得序列從局部有序逐漸變爲整體有序的一個排序過程。

那麼我們就可以想象整個過程了。

給一個序列a,我們先將其不斷二分,直到最小,然後將相鄰兩個序列進行序列之間排序、合併,並複製到a的對應範圍內。
在這裏插入圖片描述
從局部有序,一點一點就到整體有序了。

代碼

遞歸

    /*
     * @Title mergeSort
     * @Description 遞歸歸併排序
     * @author 滑技工廠
     * @Date 2020/3/17
     * @param [a, left 左指針, right 右指針]
     * @return void
     * @throws
     */
    public static void mergeSort(int a[], int left, int right) {

        if (left < right) {//劃分的持續條件
            //找到中間指針
            int i = (left + right) / 2;
            //一個序列分爲左右兩邊,分別進行mergesort,然後還會繼續劃分,
            // 直到形成一個元素一個序列的情況,就可以序列之間排序merge了
            mergeSort(a, left, i);
            mergeSort(a, i + 1, right);
            //序列排序併合併到b,left、i、right來進行劃分左右序列
            int[] b = new int[right - left + 1];
            merge(a, b, left, i, right);
            copy(a, b, left, right);

        }

    }

這裏只給出歸併排序的思路,至於merge和copy方法詳情請見我的GitHub

非遞歸

    public static void mergeSort2(int[] arr) {
        if (arr == null || arr.length <= 0)
            return;
        int width = 1;
        while (width < arr.length) {
            mergePass(arr, width);
            width *= 2;
        }
    }

    private static void mergePass(int[] arr, int width) {
        int start = 0;
        while (start + 2 * width - 1 < arr.length) {
            int mid = start + width - 1;
            int end = start + 2 * width - 1;
            merge2(arr, start, mid, end);
            start = start + 2 * width;
        }
        //剩餘無法構成完整的兩組也要進行處理
        if (start + width - 1 < arr.length)
            merge2(arr, start, start + width - 1, arr.length - 1);
    }

    private static void merge2(int[] arr, int start, int mid, int end) {
        int i = start;
        int j = mid + 1;
        int[] temp = new int[end - start + 1];
        int index = 0;
        while (i <= mid && j <= end) {
            if (arr[i] <= arr[j])
                temp[index++] = arr[i++];
            else
                temp[index++] = arr[j++];
        }
        while (i <= mid)
            temp[index++] = arr[i++];
        while (j <= end)
            temp[index++] = arr[j++];

        for (int k = start; k <= end; k++)
            arr[k] = temp[k - start];
    }

不知道爲什麼這篇閱讀量這麼少,幾天了還是4個,裏面還有我反覆看的。。。。莫非真是因爲這篇是我在交作業日期之後發的????
在這裏插入圖片描述

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