归并排序:分治思想的完美演绎
基本思想
归并排序(Merge Sort)是分治法(Divide and Conquer)的经典应用,由计算机科学先驱约翰·冯·诺依曼于 1945 年提出。其核心逻辑非常直观:将大问题分解为小问题,解决小问题后合并结果。
算法流程主要包含两个阶段:
- 分(Divide):递归地将当前数组分割成两个子数组,直到每个子数组只包含一个元素(此时天然有序)。
- 治(Conquer):将两个有序子数组合并成一个新的有序数组。
归并的核心操作是合并两个有序数组。简单来说,就是每次比较两个数组的首元素,将较小者放入新数组,直到所有元素合并完成。
#include <stdio.h>
#include <stdlib.h>
#include <string.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);
// 开始归并
int begin1 = begin, end1 = mid;
int begin2 = mid + 1, end2 = end;
int i = begin;
// 只要两边都有元素,就继续比较
while (begin1 <= end1 && begin2 <= end2) {
if (a[begin1] < a[begin2]) {
tmp[i++] = a[begin1++];
} else {
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]);
}
;
}


