【归并】
归并(Merging) :是指将两个或两个以上的有序序列合并成一个有序序列。若采用线性表(无论是那种存储结构)易于实现,其时间复杂度为O(m+n) 。
归并思想实例:两堆扑克牌,都已从小到大排好序,要将两堆合并为一堆且要求从小到大排序。
- 将两堆最上面的抽出 (设为 , ) 比较大小,将小者置于一边作为新的一堆 (不妨设 < );再从第一堆中抽出一张继续与 进行比较,将较小的放置在新堆的最下面;
- 重复上述过程,直到某一堆已抽完,然后将剩下一堆中的所有牌转移到新堆中。
【排序思想】
① 初始时,将每个记录看成一个单独的有序序列,则 个待排序记录就是 个长度为 的有序子序列;
② 对所有有序子序列进行两两归并,得到 个长度为 或 的有序子序列——一趟归并;
③ 重复② ,直到得到长度为 的有序序列为止。
上述排序过程中,子序列总是两两归并,称为2-路归并排序。其核心是如何将相邻的两个子序列归并成一个子序列。设相邻的两个子序列分别为: 和 ,将它们归并为一个有序的子序列:
完整代码如下:
#include <stdio.h>
#define TRUE 1 //真
#define FALSE 0 //假
#define OK 1 //通过
#define ERROR 0 //错误
#define MAXSIZE 20 //用作示例的顺序表的最大长度
#define LT(a,b) ((a)<(b))
#define LQ(a,b) ((a)<=(b))
typedef int Status;
/* 记录类型 */
typedef int KeyType; //定义关键字类型为整数类型
typedef struct //顺序表结构
{
KeyType key; //关键字项
//使用结构体便于使用中扩展
}RcdType;
/* 顺序表类型 */
typedef struct
{
RcdType r[MAXSIZE+1]; //r[0]闲置或用作哨兵单元
int length; //顺序表长度
}SqList_sort;
//1.创建一个任意顺序的序列。
Status CreateSortList(SqList_sort *L)
{
printf("请输入元素个数:");
scanf("%d", &((*L).length));
if((*L).length > MAXSIZE)
return ERROR;
printf("请依次输入元素的关键字:\n");
for(int i = 1; i <= (*L).length; i++)
scanf("%d", &((*L).r[i].key));
return OK;
}
//2.输出序列L。
void Traverse(SqList_sort L)
{
for(int i = 1; i <= L.length; i++)
printf("%d ", L.r[i].key);
printf("\n");
}
//3.算法10.12:将有序的SR[i..m]和SR[m+1..n]归并为有序的TR[i..n]。
void Merge(RcdType SR[], RcdType TR[], int i, int m, int n)
{
int j, k;
for(j = m+1, k = i; i <= m && j <= n; ++k) //将SR中记录由小到大地并入TR
{
if(LQ(SR[i].key, SR[j].key))
TR[k] = SR[i++];
else
TR[k] = SR[j++];
}
while(i<=m) //将剩余的SR[i..m]复制到TR
TR[k++] = SR[i++];
while(j<=n) //将剩余的SR[j..n]复制到TR
TR[k++] = SR[j++];
}
//4.算法10.13:将SR[s..t]归并排序为TR[s..t]。
void MSort(RcdType SR[], RcdType TR[], int s, int t)
{
int m;
RcdType R[MAXSIZE+1];
if(s==t)
TR[s] = SR[s];
else
{
m = (s+t)/2; //将SR[s..t]平分为SR[s..m]和SR[m+1..t]
MSort(SR, R, s, m); //递归地将SR[s..m]归并为有序的R[s..m]
MSort(SR, R, m+1, t); //递归地将SR[m+1..t]归并为有序的R[m+1..t]
Merge(R, TR, s, m, t); //将R[s..m]和R[m+1..t]归并到TR[s..t]
}
}
//5.算法10.14:对顺序表L作归并排序。
void MergeSort(SqList_sort *L)
{
MSort((*L).r, (*L).r, 1, (*L).length);
}
int main(int argc, char *argv[])
{
SqList_sort L;
CreateSortList(&L);
printf("将关键字按递增顺序排列...\n");
MergeSort(&L);
Traverse(L);
printf("\n");
return 0;
}