排序算法---合并排序(Merge Sort)

合并排序是建立在歸并操作上的一種有效的排序算法。該算法是采用分治法的一個非常典型的應用。
合并排序法是將兩個(或兩個以上)有序表合并成一個新的有序表,即把待排序序列分為若干個子序列,每個子序列是有序的。然后再把有序子序列合并為整體有序序列。
將已有序的子序列合并,得到完全有序的序列;即先使每個子序列有序,再使子序列段間有序。若將兩個有序表合并成一個有序表,稱為2-路歸并。合并排序也叫歸并排序。


算法基本思想:

  1. 首先將未排序的數組,進行拆分成n個單一的數據。
  2. 然后將這n個數據按照索引順序,兩兩組合、排序。(例如:有8個數據,那么第一個和第二個組合,第三個和第四個組合。。。如有未組合的數據這放任其暫時不管)
  3. 將上面已經兩兩組合、排序好的數據看成是一個“元素”,再進行兩兩組合、排序。。。
  4. 重復上述的步驟,最后就得到已經排序好的數組。
示意圖

代碼實現:

import java.util.Arrays;
import java.util.Date;

/**
 * Created by noonbiteun
 * Date: 2017/8/1
 */
public class MergeSort {
    private static void merge(int[] unsortArr, int frontIndex, int backIndex, int lastIndex, int[] sortArr) {
        int i = frontIndex;//前半段的起始索引
        int j = backIndex;//后半段的起始索引
        int k = 0;
        //合并兩個小分組
        while (i < backIndex && j < lastIndex) {
            if (unsortArr[i] < unsortArr[j]) {
                sortArr[k++] = unsortArr[i++];
            } else {
                sortArr[k++] = unsortArr[j++];
            }
        }
        while (i < backIndex) {
            //前半段還有數據
            sortArr[k++] = unsortArr[i++];
        }
        while (j < lastIndex) {
            //后半段還有數據
            sortArr[k++] = unsortArr[j++];
        }
        for (int l = 0; l < k; l++) {
            //將排序好的數放回
            unsortArr[frontIndex + l] = sortArr[l];
        }
    }


    public static void sort(int[] arr, int first, int last, int[] sorted) {
        if (first < last - 1) {
            int back = (first + last) / 2;
            sort(arr, first, back, sorted);
            sort(arr, back, last, sorted);
            merge(arr, first, back, last, sorted);
        }
    }

    public static void main(String[] args) {
        int[] arr = new int[10];
        //初始化數組
        for (int i = 0; i < 10; i++) {
            arr[i] = (int) (Math.random() * (100 + 1));
        }
        long t1 = new Date().getTime();
        System.out.println("原始的順序: "+ Arrays.toString(arr));
        MergeSort.sort(arr, 0, arr.length, new int[arr.length]);
        long t2 = new Date().getTime();
        System.out.println("排序后順序: "+ Arrays.toString(arr));
        System.out.println("耗時:"+(t2-t1)+" ms");
    }
}

輸出結果:

運行結果

分析小結:

歸并排序是穩定排序,它也是一種十分高效的排序,能利用完全二叉樹特性的排序一般性能都不會太差。java中Arrays.sort()采用了一種名為TimSort的排序算法,就是歸并排序的優化版本。從上文的圖中可看出,每次合并操作的平均時間復雜度為O(n),而完全二叉樹的深度為|log2n|??偟钠骄鶗r間復雜度為O(nlogn)。而且,歸并排序的最好,最壞,平均時間復雜度均為O(nlogn)。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 概述排序有內部排序和外部排序,內部排序是數據記錄在內存中進行排序,而外部排序是因排序的數據很大,一次不能容納全部的...
    Luc_閱讀 2,299評論 0 35
  • 概述 排序有內部排序和外部排序,內部排序是數據記錄在內存中進行排序,而外部排序是因排序的數據很大,一次不能容納全部...
    蟻前閱讀 5,220評論 0 52
  • 概述:排序有內部排序和外部排序,內部排序是數據記錄在內存中進行排序,而外部排序是因排序的數據很大,一次不能容納全部...
    每天刷兩次牙閱讀 3,743評論 0 15
  • 1.插入排序—直接插入排序(Straight Insertion Sort) 基本思想: 將一個記錄插入到已排序好...
    依依玖玥閱讀 1,282評論 0 2
  • 1 我說:“為什么會輪到我頭上?” 我說:“為什么不會輪到我頭上呢?” 2 每每遇到一件另我苦惱的事情,我總會這樣...
    三人生閱讀 326評論 0 0