为了解决一个给定的问题, 算法需要一次或多次地递归调用其自身来解决相关的子问题。 这些算法通常采用分治策略:
将原问题划分成n个规模较小而结构与原问题相似的子问题; 递归地解决这些子问题,然后再合并其结果,就得到原问题的解。
分治模式在每一层递归上都有三个步骤:
分解(Divide): 将原问题分解成一系列子问题;
解决(Conquer): 递归地解各个问题。若问题足够小,则直接求解;
合并(Combine): 将子问题的结果合并成原问题的解。
归并排序(merge sort)算法完全依照了上述模式, 直观地操作如下:
分解: 将n个元素分成各包含n/2个元素的子序列;
解决: 用合并排序法对两个子序列递归地排序;
合并: 合并两个已排序的子序列以得到排序结果。
归并排序的原理是 假设初始序列含有n个记录,则可以看成是n个有序的子序列,每个子序列的长度为1,
然后两两归并,得到 [ n/2 ] 个长度为2或1的有序子序列;
再两两归并...... 如此重复直至得到一个长度为n的有序序列为止,这种排序方法称为2路归并排序。
代码实现:
#define SIZE 10
/** 将有序的SR[start...mid]和SR[mid+1, end]归并为有序的TR[start...end] */
void merge(int SR[], int tempTR[], int start, int mid, int end)
{
int i, j, k;
i = start;
j = mid + 1;
k = start;
while(i <= mid && j <= end) // 注意边界条件
{
if (SR[i] < SR[j])
{
tempTR[k++] = SR[i++];
}
else
{
tempTR[k++] = SR[j++];
}
}
while(i <= mid)
{
tempTR[k++] = SR[i++]; // 将SR[start...mid]中剩余的元素复制到TR
}
while(j <= end)
{
tempTR[k++] = SR[j++];// 将SR[mid+1...end]中剩余的元素复制到TR
}
}
voide MSort(int SR[], int TR[], int s, int t)
{
int m;
int tempTR[SIZE + 1];
if (s == t) // 已分解到最小序列
TR[s] = SR[s];
else
{
m = (s + t) / 2; // 分解
MSort(SR, tempTR, s, m);
MSort(SR, tempTR, m+1, t);
merge(tempTR, TR, s, m, t); // 合并
}
}
int main()
{
int n = 10;
int TR[n];
int SR[] = {50, 10, 90, 30, 70, 40, 80, 60, 20};
MSort(SR, TR, 0, 8);
return 0;
}