归并排序:分治思想的经典实践
归并排序(Merge Sort)是分治法(Divide and Conquer)的典型应用,由约翰·冯·诺依曼于 1945 年提出。它的核心逻辑很简单:把大问题拆成小问题,解决完小问题再合并结果。
算法流程主要包含两个阶段:
- 分(Divide):递归地将当前数组分割成两个子数组,直到每个子数组只包含一个元素(单个元素天然有序)。
- 治(Conquer):将两个有序数组合并成一个新的有序数组。
归并排序的关键操作在于合并两个有序数组。每次比较两个数组的首元素,将较小者放入新数组,直到所有元素合并完成。
递归实现细节
在写递归代码时,区间划分是个容易踩坑的地方。我们来看具体的 C 语言实现。
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
// 辅助函数:合并两个有序区间 [begin, mid] 和 [mid+1, end]
void _MergeSort(int* a, int* tmp, int begin, int end) {
// 递归终止条件:当子数组只有一个元素时,无需再分
if (begin == end) {
return;
}
// 计算中间点
int mid = (begin + end) / 2;
// 注意:这里区间分为 [begin, mid] 和 [mid+1, end]
// 如果分成 [begin, mid-1] 和 [mid, end] 会导致死循环或逻辑错误
_MergeSort(a, tmp, begin, mid);
_MergeSort(a, tmp, mid + 1, end);
// 归并过程
begin1 = begin, end1 = mid;
begin2 = mid + , end2 = end;
i = begin;
(begin1 <= end1 && begin2 <= end2) {
(a[begin1] < a[begin2]) {
tmp[i++] = a[begin1++];
} {
tmp[i++] = a[begin2++];
}
}
(begin1 <= end1) {
tmp[i++] = a[begin1++];
}
(begin2 <= end2) {
tmp[i++] = a[begin2++];
}
(a + begin, tmp + begin, (end - begin + ) * ());
}
{
* tmp = (*)(() * n);
(tmp == ) {
perror();
;
}
_MergeSort(a, tmp, , n - );
(tmp);
tmp = ;
}
{
a[] = {, , , , , };
MergeSort(a, );
( i = ; i < (a) / (a[]); i++) {
(, a[i]);
}
;
}


