1. 程式人生 > >歸併排序-java實現

歸併排序-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],來看下實現步驟 這裡寫圖片描述

程式碼實現:

package Sort.Merge;

import Common.Common;
//自頂向下的歸併排序
public class Merge {
    private static void sort(int[] a,int low,int high) {
        int mid=(low+high)/2;
        if (low<high) {
            sort(a, low, mid);//左邊歸併排序,使得左子序列有序
            sort(a, mid+1, high);//右邊歸併排序,使得右子序列有序
            merge(a, low, mid, high);//將兩個有序子數組合並操作
} } 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++]; } } // System.out.println(k); //將右邊未放完的元素繼續放入臨時陣列 while (i<=mid) { temp[k++]=a[i++]; } //將左邊未放完的元素繼續放入臨時陣列 while (j<=high) { temp[k++]=a[j++]; } //將臨時陣列元素放入原陣列中 for (int x = 0; x < temp.length; x++) { a[x+low]=temp[x]; } } public static void main(String[] args) { int[] in= {1,5,4,3,7,9,8,6}; int low=0; int high=in.length-1; sort(in, low, high); for (int i = 0; i < in.length; i++) { System.out.print(in[i]+" "); } } }

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