合并排序使用了“分治法”的策略。
“将原问题划分成n个规模较小而结构与原问题相似的子问题;递归地解决这些子问题;然后合并其结果,就得到原问题的解。”这就是分治策略。
分治策略在每一层递归上有以下三个步骤:
1)分解:将原问题分解成一系列子问题;
2)解决:递归地解各子问题;
3)合并:将子问题的解合并成原问题的解。
合并排序依照上述策略:
1)分解:将n个元素分成两个含n/2个元素的子序列;
2)解决:用合并排序法对两个子序列递归地排序;
3)合并:合并两个已排序的子序列以得到排序结果。
以下代码演示了合并排序算法:
#include <iostream> #include <limits> using namespace std; /*合并A[p...q]和A[q+1...r]数组,初始条件为两个字数组均有序,合并后A[p...r]有序*/ void merge(int A[], int p, int q, int r); /*合并排序,排序后,A[p...r]为非递减数组*/ void mergeSort(int A[], int p, int r); int main() { int A[10] = {20, 31, 14, 5, 11, 7, 83, 3, 5, 67}; for(int i = 0; i < 10; i++) cout << A[i] << " "; cout << endl; mergeSort(A, 0, 9); for(int i = 0; i < 10; i++) cout << A[i] << " "; cout << endl; return 0; } void merge(int A[], int p, int q, int r) { int n1 = q - p + 1; //字数组A[p...q]长度 int n2 = r - q; //字数组A[q+1...r]长度 int L[n1 + 1]; //辅助数组 int R[n2 + 1]; //辅助数组 /*初始化*/ for(int i = 0; i < n1; i++) L[i] = A[p + i]; for(int i = 0; i < n2; i++) R[i] = A[q + 1 + i]; L[n1] = numeric_limits<int>::max(); //末端置最大值,作哨兵 R[n2] = numeric_limits<int>::max(); //同上 /*以下循环将L,R字数组合并到A数组*/ int i = 0, j = 0; for(int k = p; k <= r; k++) { if(L[i] <= R[j]) { A[k] = L[i]; i++; } else { A[k] = R[j]; j++; } } } void mergeSort(int A[], int p, int r) { if(p >= r) return ; //结束条件 /*分解*/ int q = (p + r) / 2; //取“中间”数作为分界点 /*解决*/ mergeSort(A, p, q); //递归排序 mergeSort(A, q + 1, r); //同上 /*合并*/ merge(A, p, q, r); }