歸併排序-java實現
阿新 • • 發佈:2018-12-09
基本思想: 歸併排序(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)。