【圖解演算法】排序演算法——歸併排序
阿新 • • 發佈:2019-01-22
0.什麼是歸併排序(Merge sort)?
是建立在歸併操作上的一種有效的排序演算法,效率為O(n log n)。1945年由約翰·馮·諾伊曼首次提出。該演算法是採用分治法(Divide and Conquer)的一個非常典型的應用,且各層分治遞迴可以同時進行。(from zh.wikipedia.org)
我對歸併排序的理解是——分而治之,就是一個問題看起來很複雜,那就將他分開處理,這也是遞迴的思想; 就拿排序這件事件來說,對一個數組的排序,我們可以將他分成兩個陣列來處理,再對這兩個陣列同樣的道理來處理,將他們分別分成兩個陣列來處理…… 直到陣列無法再細分下去(即陣列的長度為1,只有一個元素的陣列肯定是有序的),分為之後的陣列進行合併操作,向上整合整個陣列,最後到達得到一個有序的陣列的目的。
可能這樣說得很抽象,我們一起來看歸併排序的動態處理元素的圖例:
看著圖的同時再來看一看具體的程式碼實現過程:
public static void main(String [] args){
int[] t = {18,7,8,6,33,2,9,1};
mergSort(t,0,7);
for (int i = 0;i<t.length;i++)
System.out.print(t[i] + "\t");
}
public static void mergSort(int [] arr,int l,int r){
if(l>=r) return;
int mid = (l+r)/2;
//遞迴二分 將陣列分為 [左,中],(中,右]
mergSort(arr,l,mid);
mergSort(arr,mid+1,r);
//歸併排序
int aux[] = new int[r-l+1]; //這裡弄一個要處理的陣列副本 長度是 R-L+1
for (int i =l;i<=r ;i++) //副本陣列從 L 開始,所以與原陣列存在一個 L 的偏移量
aux[i-l] = arr[i];
int i = l,j = mid+1; //i記錄左邊元素的下標位置 j記錄右邊元素的下標位置
for (int k =l;k <= r; k++){ //k記錄 arr 的下標位置
if(i >mid){
arr[k] = aux[j-l];
j++;
}else if(j >r){
arr[k] = aux[i-l];
i++;
}else if(aux[i-l] < aux[j-l]){
arr[k] = aux[i-l];
i++;
}else{
arr[k] = aux[j-l];
j++;
}
}
}
程式輸出:
1 2 6 7 8 9 18 33