#include <stdio.h>
#include <stdlib.h>
/**整体思想:分治 + 递归*/
// 归并两个已经有序的数组,L、M和R分别是左边界、分界点和右边界
// 这里将右边数组的第一个元素的下标作为了分界点
void merge(int array[], int L, int M, int R) {
// 求出左右两部分数组的大小
int LEFT_SIZE = M - L;
int RIGHT_SIZE = R - M + 1;
// 分别定义左右两个数组存放原数组中左右两边的数据
int left[LEFT_SIZE];
int right[RIGHT_SIZE];
int i, j, k;
// 填上左边的数组
for (i = L; i < M; i++) {
left[i - L] = array[i];
}
// 填上右边的数组
for (i = M; i <= R; i++) {
right[i - M] = array[i];
}
// 初始化三个变量为对应数组的起始位置
// i: 指向left数组的起始位置
// j: 指向right数组的起始位置
// k: 指向array数组的起始位置
i = 0;
j = 0;
k = L;
// 比较left和right数组中i和j指向的元素的大小进行归并,将元素填充到array数组中
while (i < LEFT_SIZE && j < RIGHT_SIZE) {
if (left[i] < right[j]) {
array[k] = left[i];
i++;
k++;
} else {
array[k] = right[j];
j++;
k++;
}
}
// 将left或者right数组中剩余的元素填充到array数组中
while (i < LEFT_SIZE) {
array[k] = left[i];
i++;
k++;
}
while (j < RIGHT_SIZE) {
array[k] = right[j];
j++;
k++;
}
}
// 实现分治,将数组不断二分的过程
void merge_sort(int array[], int L, int R) {
// 如果这一段只有一个元素,那么它一定是有序的
if (L == R) {
return ;
} else { // 否则将数组二分
int M = (L + R) / 2;
merge_sort(array, L, M);
merge_sort(array, M + 1, R);
// 这里需要注意,我们这里求出来的M和上面merge函数中传过去的M
// 表示的位置实际上是不一样的,这里求出来的M刚好指向了左半边
// 数组的最后一个元素,而merge函数中需要的M指向的是右半边数组
// 的第一个元素,所以这里把M加1当作参数传给merge函数进行调用
merge(array, L, M + 1, R);
}
}
int main()
{
// 定义测试数组
int array[] = {7, 3, 4, 9, 2, 1, 0, 13};
int L = 0;
int R = 7;
// 调用归并函数进行排序
merge_sort(array, L, R);
// 遍历展示
int i;
for (i = 0; i <= R; i++) {
printf("%d\n", array[i]);
}
return 0;
}
运行结果: