1.算法說明算法
[1]歸併算法,指的是將兩個已經排序的序列合併成一個序列的操做。數組
[2]該算法採用的是分治法思想。函數
2.算法代碼spa
#include <stdlib.h> #include <stdio.h> #define ARRAY_LEN 8 static void print_array(int *array, int len) { int i; for(i=0; i<len; i++){ printf("%d ", array[i]); } printf("\n"); } /*排序start到end的元素*/ static void merge(int array[], int start, int middle, int end) { int i,j,k; int temp_array[ARRAY_LEN]; //temp_array的做用就是把排序好序列放到此上面,而後再拷貝給array。 i = start; j = middle + 1; k = start; while(i != middle + 1 && j != end + 1){ if(array[i] > array[j]) temp_array[k++] = array[j++]; else temp_array[k++] = array[i++]; } while(i != middle + 1) temp_array[k++] = array[i++]; while(j != end + 1) temp_array[k++] = array[j++]; for(i=start; i<=end; i++) array[i] = temp_array[i]; } static void merge_sort(int array[], int start, int end, int dir) { int middle; if(start < end){ middle = start + (end - start) / 2; merge_sort(array, start, middle, -1); merge_sort(array, middle + 1, end, 1); merge(array, start, middle, end); printf("merge, dir:%-2d :", dir); print_array(array, 8); } } int main() { int array[ARRAY_LEN] = {8,7,6,5,4,3,2,1}; printf("start array:\n\t"); print_array(array, ARRAY_LEN); printf("\n"); merge_sort(array, 0, ARRAY_LEN - 1, 0); printf("\nend array:\n\t"); print_array(array, ARRAY_LEN); printf("\n"); return 0; }
[1]上面代碼輸出結果:code
start array: 8 7 6 5 4 3 2 1 merge, dir:-1 :7 8 6 5 4 3 2 1 merge, dir:1 :7 8 5 6 4 3 2 1 merge, dir:-1 :5 6 7 8 4 3 2 1 merge, dir:-1 :5 6 7 8 3 4 2 1 merge, dir:1 :5 6 7 8 3 4 1 2 merge, dir:1 :5 6 7 8 1 2 3 4 merge, dir:0 :1 2 3 4 5 6 7 8 end array: 1 2 3 4 5 6 7 8
[2]中間的7行是每次調用merge()函數以後的結果,dir表示排序的方向,-1表示排序左側,0表示排序整個數組,1表示排序右側。blog
[3]代碼流程:排序
1)首先把數組分爲左右兩側,即[8,7,6,5]和[4,3,2,1],而後先排序左側,再排序右側。遞歸
2)繼續排序時,就是一個遞歸流程,即排[8,7],再排[6,5],再排[7,8]和[5,6],再排[4,3],再排[2,1],再排[3,4]和[1,2],最後排[5,6,7,8]和[1,2,3,4]。隊列
4.總結io
[1]歸併排序的流程就是,把兩個有序隊列合併成一個有序隊列,就是merge()函數,這個函數仍是很簡單的。
[2]若是要排序兩個有序隊列,那麼只用一個merge()函數就夠了。可是算法的應用是要排序一個無序數組,所以其中用到了遞歸,遞歸只是一種實現方式,固然也能夠用迭代方式實現。參考下面的代碼:
/*排序兩個有序數組*/ static void merge_sort(int array[], int start, int end, int dir) { int middle; if(start < end){ middle = start + (end - start) / 2; merge(array, start, middle, end); } } /* 遞歸排序數組,這裏只分析最外層的merge_sort() */ static void merge_sort(int array[], int start, int end, int dir) { int middle; if(start < end){ middle = start + (end - start) / 2; merge_sort(array, start, middle, -1); //這個函數返回時,表示左側已經排序好,即此時數組是[5,6,7,8,4,3,2,1] merge_sort(array, middle + 1, end, 1); //這個函數返回時,表示右側已經排序好,即此時數組是[5,6,7,8,1,2,3,4] merge(array, start, middle, end); } }
[3]以此來分析遞歸的實際流程,遞歸會層層進入內部,以後層層調用merge()函數。這也就是說,遞歸的意思就是層層調用一個具體的執行函數。通常的說來,遞歸是調用本身,明白了遞歸的層層入口點,也明白了層層返回點,可是這樣理解老是找不到遞歸的重點,所以更容易的理解是,遞歸是層層調用一個具體的執行函數。而後最內層調用執行函數後,array會有新的排列,次內層調用執行函數後,array又會有新的排列,最外層調用執行函數後,數組就會排序完成。