1. 程式人生 > >【排序演算法】歸併排序原理及Java實現

【排序演算法】歸併排序原理及Java實現

1、基本思想:

歸併排序就是利用歸併的思想實現的排序方法。而且充分利用了完全二叉樹的深度是這裡寫圖片描述的特性,因此效率比較高。其基本原理如下:對於給定的一組記錄,利用遞迴與分治技術將資料序列劃分成為越來越小的半子表,在對半子表排序,最後再用遞迴方法將排好序的半子表合併成為越來越大的有序序列。
經過第一輪比較後得到最小的記錄,然後將該記錄的位置與第一個記錄的位置交換;接著對不包括第一個記錄以外的其他記錄進行第二次比較,得到最小記錄並與第二個位置記錄交換;重複該過程,知道進行比較的記錄只剩下一個為止。

2、複雜度分析

一趟歸併需要將陣列 a[]中相鄰的長度為h的有序序列進行兩兩歸併.並將結果放到temp[]中,這需要將待排序列中的所有記錄掃描一遍,因此耗費O(n)

,而又完全二叉樹的深度可知,整個歸併排序需要進行(這裡寫圖片描述)次,因此總的時間複雜度為O(nlogn),而且這是歸併排序演算法中最好、最壞、平均的時間效能。
由於歸併排序在歸併過程中需要與原始序列同樣數量的儲存空間存放歸併結果以及遞迴時深度為這裡寫圖片描述的棧空間,因此空間複雜度為O(n+logn).
另外,對程式碼進行仔細研究,發現merge函式中有if (a[i] < a[j]) 的語句,說明它需要兩兩比較,不存在跳躍,因此歸併排序是一種穩定的排序演算法。
也就是說,歸併排序是一種比較佔記憶體,但卻效率高且穩定的演算法。

3、工作原理:

(1)申請空間,使其大小為兩個已經排序序列之和,該空間用來存放合併後的序列
(2)設定兩個指標,最初位置分別為兩個已經排序序列的起始位置
(3)比較兩個指標所指向的元素,選擇相對小的元素放入到合併空間,並移動指標到下一位置
(4)重複步驟3直到某一指標達到序列尾
(5)將另一序列剩下的所有元素直接複製到合併序列尾

4、歸併排序過程如下:

以陣列{50,10,90,30,70,40,80,60,20}為例,

這裡寫圖片描述

最後的排序結果:
10,20,30,40,50,60,70,80,90

4、Java實現如下:

public class MergeSort {

    public static void merge(int[] a, int low, int mid, int high) {
        int[] temp = new int[high - low + 1];
        int i = low;// 左指標
        int j = mid + 1;// 右指標
        int k = 0
; // 把較小的數先移到新陣列中 while (i <= mid && j <= high) { if (a[i] < a[j]) { temp[k++] = a[i++]; } else { temp[k++] = a[j++]; } } // 把左邊剩餘的數移入陣列 while (i <= mid) { temp[k++] = a[i++]; } // 把右邊邊剩餘的數移入陣列 while (j <= high) { temp[k++] = a[j++]; } // 把新陣列中的數覆蓋nums陣列 for (int k2 = 0; k2 < temp.length; k2++) { a[k2 + low] = temp[k2]; } } public static void mergeSort(int[] a, int low, int high) { int mid = (low + high) / 2; if (low < high) { // 左邊 mergeSort(a, low, mid); // 右邊 mergeSort(a, mid + 1, high); // 左右歸併 merge(a, low, mid, high); System.out.println(Arrays.toString(a)); } } public static void main(String[] args) { int a[] = { 51, 46, 20, 18, 65, 97, 82, 30, 77, 50 }; mergeSort(a, 0, a.length - 1); System.out.println("排序結果:" + Arrays.toString(a)); } }