利用递归与分治技术将数据序列划分为越来越小的半子表,再对半子表排序,最后再用递归步骤将排好序的半子表合并成为越来越大的有序序列。
原理如下:对于给定的一组记录,首先将两个相邻的长度为1的子序列进行归并,得到n/2个长度为2或者1的有序子序列,在将其两两归并,反复执行此过程,直到得到一个有序的序列为止。
#include <stdio.h>
#include <stdlib.h>
void Merge(int array[], int start, int middle, int end)
{
int i, j, k, n1, n2;
n1 = middle - start + 1; //前半部分序列长度
n2 = end - middle; //后半部分序列长度
int *L = (int *)malloc(n1 * sizeof(int)); //前半部分临时数组
int *R = (int *)malloc(n2 * sizeof(int)); //后半部分临时数组
for (i = 0, k = start; i < n1; i++, k++) //将原序列的前半部分复制到临时数组中
{
L[i] = array[k];
}
for (i = 0, k = middle + 1; i < n2; i++, k++) //将后序列的前半部分复制到临时数组中
{
R[i] = array[k];
}
// 先比较对应位置的数值,将最小值(假设是下标L[0])写入原序列后,i 变成 1
// 继续比较下标L[1]与R[0],如果L[1] < R[0],继续将L[1]写入原序列,i变成2
//i不再满足循环条件(假设本次左半部分长度为2),循环结束,但R数组中还有两个数未写入
//那么,就将这两个数按顺序写入序列
for (k = start, i = 0, j = 0; i < n1 && j < n2; k++)
{
if (L[i] < R[j])
{
array[k] = L[i];
i++;
}
else
{
array[k] = R[j];
j++;
}
}
if (i < n1) //如果L数组中还有剩余的数,则按顺序写入原数组中
{
for (j = i; j < n1; j++, k++)
{
array[k] = L[j];
}
}
if (j < n2) //如果R数组中还有剩余的数,则按顺序写入原数组中
{
for (i = j; i < n2; i++, k++)
{
array[k] = R[i];
}
}
}
void MergeSort(int array[], int start, int end)
{
int middle;
int i;
if (start < end)
{
middle = (start + end) / 2; //将序列一分为二
MergeSort(array, start, middle); //左半部分,递归继续拆分,直到单个
MergeSort(array, middle + 1, end); //右半部分,递归继续拆分,直到单个
Merge(array, start, middle, end); //待整个序列全部拆分完毕后,从最低层开始排序合并
}
}
int main()
{
int i = 0;
int a[] = {29, 17, 35, 6, 12, 31, 28, 15};
int length = sizeof(a) / sizeof(a[0]);
MergeSort(a, 0, length -1);
for (i = 0 ; i < length; i++)
{
printf("%d ", a[i]);
}
printf("\n");
return 0;
}