归并排序:分解待排序的n个元素的序列成各具n/2个元素的两个子序列;使用归并排序递归地排序这两个子序列;合并两个已排序好的子序列生成最终答案。
当排序的子序列长度为1时,递归开始向上合并,直到整个序列排序结束。
其中关键步骤是合并两个子序列:假设桌面有两堆牌面向上的牌,每堆都已经排好序,最小的牌在上面。我们从两堆牌的顶端选取较小的一张,移动到输出堆,并朝下放置。重复这个动作,直到两个堆为空。为了避免在每个步骤都检查是否堆为空,设置两张哨兵牌分别放置在两个堆的最下,选取最大值无穷大,当执行两堆牌总数步时,程序结束。
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
void merge_sort(int *,int,int);//归并排序函数
main()
{
int a[10] = {3,6,34,54,32,45,23,67,3,54};
int i;
merge_sort(a,0,9);
for(i = 0;i < 10;i++)
printf("%d ",a[i]);
printf("\n");
}
void merge_sort(int *a,int n1,int n2)
{
int q;
void merge(int *,int,int,int);
if (n1 < n2) {
q = (n1 + n2) / 2;//把整个数组序列平均分成两组,递归执行,直到每个组数量为1
merge_sort(a,n1,q);
merge_sort(a,q+1,n2);
merge(a,n1,q,n2);
}
}
void merge(int *a,int p,int q,int r)//合并过程
{
int n1,n2,i,j,k;
int *L,*R;
n1 = q - p + 1;
n2 = r - q;
L = malloc((n1 + 1) * sizeof(int));
R = malloc((n2 + 1) * sizeof(int));
for (i = 0;i < n1;i++)
L[i] = a[p+i];
for (j = 0;j < n2;j++)
R[j] = a[q+j+1];
L[n1] = INT_MAX;//哨兵牌
R[n2] = INT_MAX;
for (i = 0,j = 0,k = p;k <= r;k++) {
if (L[i] <= R[j]) {
a[k] = L[i];
i++;
}
else {
a[k] = R[j];
j++;
}
}
free(L);
free(R);
}