歸并排序的原理
歸并排序的思想是如果要排序一個數組,需要把數組分為兩部分,然后對兩部分分別進行排序,再將排序好的數組合并起來。歸并排序其實分為兩個步驟,先進行待排數據的分解,再對最小集進行排序,在進行合并。
歸并排序其實就是一個分治的思想,分一般采用的形式是遞歸來解決的,而治在這里指的是把各階段的答案拼在一起。
image
歸并排序的偽代碼
第一個方法{
創建一個和原數組一樣大的臨時數組。
調用第二個方法,參數為0,數組長度-1,原數組,臨時數組temp
}
第二個方法
{
遞歸的出口是數組的長度為1。
對待排序數組進行二分,分為左分區,和右分區。
遞歸的進行切分下去
對左分區和右分區進行merge操作,合并數組。merge方法傳入的參數為:待排序區間的邊界索引(三個),原數組,臨時數組
}
第三個方法merge{
遍歷待排區間,依次比較左區間右區間的數的大小,小的數放到臨時區間中,直到某個區間遍歷完成
遍歷未遍歷完的剩余區間的數,依次追加到臨時數組。
拷貝臨時數組至原數組中。
}
代碼示例
public class MergeSort {
public static void main(String[] args){
int a[] = {9,8,7,6,5,4,3,2,1,0};
mergeSort(a);
System.out.println("ok:" + Arrays.toString(a));
}
public static void mergeSort (int[] num){
if(num==null || num.length==1){
return;
}
int[] temp = new int[num.length];
sort(num,temp,0,num.length-1);
}
public static void sort(int[] num,int[] temp,int left,int right){
if(left>=right){
return;
}
int mid = (left+right)/2;
sort(num,temp,left,mid);
sort(num,temp,mid+1,right);
merge(num,temp,left,mid,right);
System.out.println(Arrays.toString(num));
}
public static void merger(int[] arr,int[] temp,int left,int mid,int right){
int k = left;
int l = left;
int r = mid+1;
while(l<=mid && r<=right){
if(arr[l]<=arr[r]){
temp[k++]=arr[l++];
}else{
temp[k++]=arr[r++];
}
}
while (l <= mid) { // 左邊如果有剩余
temp[k++] = arr[l++];
}
while (r <= right) { // 右邊如果有剩余
temp[k++] = arr[r++];
}
for(int i = left;i<=right;i++){
arr[i]=temp[i];
}
}
}
性能分析
最佳情況:T(n) = O(n)
最差情況:T(n) = O(nlogn)
平均情況:T(n) = O(nlogn)
對于長度為 N 的任意數組,自頂向下的歸并排序需要 1/2NlgN - NlgN 次比較。
對于長度為 N 的任意數組,自頂向下的歸并排序最多需要訪問數組 6NlgN 次(2N 次用來復制、2N 次用來將排好序的元素移動回來、另外最多比較 2N 次)。