二路歸併排序主要運用了「分治算法」,分治算法就是將一個大的問題劃分爲n個規模較小而結構類似的子問題。算法
這些子問題解決的方法都是相似的,解決掉這些小的問題以後,歸併子問題的結果,就獲得了「大」問題的解。數組
二路歸併排序主旨是「分解」與「歸併」spa
分解: 指針
1.將一個數組分紅兩個數組,分別對兩個數組進行排序。code
2.循環第一步,直到劃分出來的「小數組」只包含一個元素,只有一個元素的數組默認爲已經排好序。blog
歸併:排序
1.將兩個有序的數組合併到一個大的數組中。io
2.從最小的只包含一個元素的數組開始兩兩合併。此時,合併好的數組也是有序的。class
圖1. 歸併排序過程 圖2. 合併兩個有序數組循環
舉例說明:
1.圖中原始數組爲{2,4,7,5,8,1,3,6},數組中元素的個數爲8個。首先將8個元素的數組二分,每次分解後,
數組中元素的數目爲原數組的通常。直到分解爲只含有一個元素的數組。
2.將小的數組按序合併,每次合併後數組的大小爲上層數組的一倍。此時數組中的元素都是按序排列的。
3.在合併兩個有序數組。如圖2
(1) 合併時,有兩個指針分別指向有序數組A和B的起始元素,比較指針所指元素的大小,若是A[i]較小,則將A[i]
存入數組C中,而且將i後移。循環比較i和j所指的元素。
(2)當一個數組A的元素所有排以後,數組B中的指針就並無指向B的末尾位置,將B中剩餘元素所有存入到C中。
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 void Merge(int array[], int p, int q, int r); 5 void MergeSort(int array[], int p, int q); 6 7 int main() 8 { 9 //int array[7] = {1,3,5,2,4,5,10}; 10 int array[8] = {5,2,4,7,1,3,2,6}; 11 int i = 0; 12 13 MergeSort(array, 0, 7); 14 //Merge(array, 0, 2, 6); 15 16 for(i; i < 8; i++) 17 printf("%d ", array[i]); 18 return 0; 19 } 20 21 //合併過程當中 p<=q<r 22 void Merge(int array[], int p, int q, int r) 23 { 24 int n1 = q - p + 1; 25 int n2 = r - q; 26 27 int *L; 28 L = (int*)malloc(sizeof(int)*n1); 29 int *R; 30 R = (int*)malloc(sizeof(int)*n2); 31 32 int i = 0; 33 int j = 0; 34 35 for(i; i < n1; i++) 36 L[i] = array[i + p]; 37 for(j; j < n2; j++) 38 R[j] = array[j + q +1]; 39 40 i = j = 0; 41 42 int k = p; 43 44 while(i!=n1 && j!= n2) 45 { 46 if(L[i] <= R[j]) 47 array[k++] = L[i++]; 48 else 49 array[k++] = R[j++]; 50 } 51 52 while(i < n1) 53 array[k++] = L[i++]; 54 while(j < n2) 55 array[k++] = R[j++]; 56 57 free(L); 58 free(R); 59 } 60 61 void MergeSort(int array[], int p, int q) 62 { 63 if(p < q) 64 { 65 int r = (p+q)/2; 66 MergeSort(array, p, r); 67 MergeSort(array, r+1, q); 68 Merge(array,p, r, q); 69 } 70 }
參考資料:《算法導論》2.1章節
若是有什麼問題,請給我留言,我會改正,咱們共同進步。謝謝~