#include <iostream> using namespace std; //歸併算法 /** 一句箴言:將待排序數據一分爲二,二分爲四,四分爲八,遞歸下去,直至每份爲1個元素,這一個元素自身必定爲有序的,而後再將分了的兩兩合併爲有序數組,最終變成一個有序數組。 方法:遞歸拆分並兩兩合併爲有序數組。其中合併時候須要將待合併的兩組數據拷貝出來,指定左待歸併數據索引i,右待歸併數據索引j, k爲原數組需從新指定值得索引 **/ void _merge(int arr[], int l, int mid, int r) { //歸併前判斷是否分割的兩數組已經左邊小右邊大了 if (arr[mid+1] > arr[mid]) { return; } //首先須要拷貝出待歸併區間的數據 區間爲索引l到 r int aux[r - l + 1]; for (int i = l ; i <= r; i++) { aux[i - l] = arr[i]; } /** // 註釋的是去除掉偏移量l後的數組 求解法 int max = r -l; int newMid = (max - min) / 2; int i = 0,j = newMid + 1; //遍歷原數組l到 r 這個區間,走待歸併的兩個區間裏選擇最小的去填充覆蓋 for (int k = l; k <= r; k++) { //當左邊的都已經賦值完,索引已經越過中間點,則只剩下右邊的了 if (i > newMid ) { arr[k] = aux[j]; j++; } else if (j > max) { arr[k] = aux[i]; i++; } else if(aux[i] < aux[j]) { arr[k] = aux[i]; i++; } else { arr[k] = aux[j]; j++; } } **/ int i = l,j = mid + 1; //遍歷原數組l到 r 這個區間,走待歸併的兩個區間裏選擇最小的去填充覆蓋 for (int k = l; k <= r; k++) { //當左邊的都已經賦值完,索引已經越過中間點,則只剩下右邊的了 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++; } } } void mergeSort(int arr[], int l, int r) { //遞歸則首先要找到跳出條件 if (l >= r) { return ; } //一分爲二,遞歸調用本身排序 int mid = (r + l) / 2; mergeSort(arr, l, mid); mergeSort(arr, mid+1, r); //歸併 _merge(arr, l, mid, r); } int main() { int arr[10] = {10,9,8,7,6,5,4,3,2,1}; mergeSort(arr, 0, 9); for(int i =0; i< 10; i++) { cout << arr[i] << " "; } return 0; }