歸併排序採用分治法的思想,將要排序的數分紅一個個子問題,最終再將子問題合併,結構上是遞歸的,並且不少有用的算法結構上都是遞歸的,對遞歸的理解必定要透徹,如根據樹的前序遍歷和中序遍歷恢復出原樹,就採用了遞歸算法,整體思想我認爲是將遞歸處理當作一個問題去處理,處理順序也當成一個問題去思考。接下里經過對歸併排序的分析,深刻描述一下這種思考方式。java
分治法的思想精髓在將原問題分解爲幾個規模較小但相似於原問題的子問題,遞歸的求解這些子問題,而後再合併這些子問題的解來創建原問題的解。分治在每層遞歸時都有三個步驟:算法
1.分解原問題爲若干子問題。spa
2.解決這些子問題,遞歸的求解,若是子問題足夠小,則直接得解。code
3.合併這些子問題的解爲原問題的解。blog
歸併排序則徹底遵照分治的三個步驟:排序
1.分解n個元素序列成各劇有n/2的元素的子序列。遞歸
2.遞歸解決子問題,歸併排序解決的最小子問題爲一個元素,可直接得解。class
3.合併子問題。遍歷
當子問題爲1時或待分解序列不可再分時,歸併開始回升。程序
接下來分析歸併排序的複雜度,分解問題使用的複雜度爲常數,解決須要n*lgn,合併須要n。
歸併排序的遞歸樹的深度爲lgn+1,如序列爲16個元素,則分解到每一個元素只有一個的時候,須要lgn+1次分解,也就是5次,16->8,8->4,4,4,4->2,2,2,2,2,2,2,2->16*1
下面給出歸併排序的java實現。
public class Main { public static void main(String args[]){ int[] a = {8,7,6,5,4,3,2,1}; MERGE_sort(a,0,7); while(true); } public static void MERGE_sort(int[] a,int p,int r){ if(p<r){
//遞歸思想,歸併排序的主體過程就是 先將問題分爲兩個子問題,而後解決,合併,將這三個步驟不斷遞歸,編寫程序時,只用考慮一次遞歸的過程就行,這一次的遞歸過程就簡單的寫爲,排序左側,排序右側,合併。同時要加上條件判斷和向深層遞歸的變化。 int q = (p+r)/2; MERGE_sort(a,p,q); MERGE_sort(a,q+1,r); MERGE(a,p,q,r); } } public static void MERGE(int[] a,int p,int q,int r){ int n1 = q-p+1; int n2 = r-q; int[] L = new int[n1+1]; int[] R = new int[n2+1]; for(int i = 0;i < n1;i++){ L[i] = a[p+i]; } L[n1] = 55; //哨兵值 可改爲正無窮 for(int i = 0;i < n2;i++){ R[i] = a[q+1+i]; } R[n2] = 55; //哨兵值 int i=0,j=0; for(int k = p;k<=r;k++){ if(L[i] == 55){ for(int v = j;v<n2;v++){ a[k] = R[v]; k++; } break; } if(R[j] == 55){ for(int v = i;v<n1;v++){ a[k] = L[v]; k++; } break; } if(L[i]<=R[j]){ a[k] = L[i]; i++; } else{ a[k] = R[j]; j++; } } } }