归并排序(第十章 P283 算法10.12,10.13,10.14)

2-路归并排序

 

概述:

归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。

 

 

排序过程:

 

看成是 n 个有序的子序列(长度为 1),然后两两归并。

得到 n/2 个长度为2 或 1 的有序子序列。继续两两归并

最后一趟

 

 

算法性能:

 

时间复杂度:

每趟归并的时间复杂度为O(n),共需进行 log2 n 趟。

二路归并排序的时间复杂度:等于归并趟数与每一趟时间复杂度的乘积。时间复杂度为O(nlog2n)。

空间复杂度:

利用二路归并排序时,需要利用与待排序数组相同的辅助数组作临时单元,故该排序方法的空间复杂度为O(n)。

稳定性:

由于二路归并排序中,每两个有序表合并成一个有序表时,若分别在两个有序表中出现有相同排序码,则会使前一个有序表中相同排序码先复制,后一有序表中相同排序码后复制,从而保持它们的相对次序不会改变。所以,二路归并排序是一种稳定的排序方法。

 

 

代码:

 

#include<stdio.h> /* EOF(=^Z或F6),NULL */

 /*  对两个数值型关键字的比较约定为如下的宏定义 */
#define EQ(a,b) ((a)==(b))
#define LT(a,b) ((a)<(b))
#define LQ(a,b) ((a)<=(b))


typedef int InfoType; /* 定义其它数据项的类型 */

/* ---------------------------    待排记录的数据类型     ------------------------------*/

#define MAXSIZE 20 /* 一个用作示例的小顺序表的最大长度 */
typedef int KeyType; /* 定义关键字类型为整型 */
typedef struct
{
	KeyType key; /* 关键字项 */
	InfoType otherinfo; /* 其它数据项,具体类型在主程中定义 */
}RedType; /* 记录类型 */

typedef struct
{
	RedType r[MAXSIZE + 1]; /* r[0]闲置或用作哨兵单元 */
	int length; /* 顺序表长度 */
}SqList; /* 顺序表类型 */


/* ------------------------------------------------------------------------------------------*/


void Merge(RedType SR[], RedType TR[], int i, int m, int n)
{ /* 将有序的SR[i..m]和SR[m+1..n]归并为有序的TR[i..n] 算法10.12 */
	int j, k, l;
	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++];
	if (i <= m)
		for (l = 0; l <= m - i; l++)
			TR[k + l] = SR[i + l]; /* 将剩余的SR[i..m]复制到TR */
	if (j <= n)
		for (l = 0; l <= n - j; l++)
			TR[k + l] = SR[j + l]; /* 将剩余的SR[j..n]复制到TR */
}

void MSort(RedType SR[], RedType TR1[], int s, int t)
{ /* 将SR[s..t]归并排序为TR1[s..t]。算法10.13 */
	int m;
	RedType TR2[MAXSIZE + 1];
	if (s == t)
		TR1[s] = SR[s];
	else
	{
		m = (s + t) / 2; /* 将SR[s..t]平分为SR[s..m]和SR[m+1..t] */
		MSort(SR, TR2, s, m); /* 递归地将SR[s..m]归并为有序的TR2[s..m] */
		MSort(SR, TR2, m + 1, t); /* 递归地将SR[m+1..t]归并为有序的TR2[m+1..t] */
		Merge(TR2, TR1, s, m, t); /* 将TR2[s..m]和TR2[m+1..t]归并到TR1[s..t] */
	}
}

void MergeSort(SqList *L)
{ /* 对顺序表L作归并排序。算法10.14 */
	MSort((*L).r, (*L).r, 1, (*L).length);
}

void print(SqList L)
{
	int i;
	for (i = 1; i <= L.length; i++)
		printf("(%d,%d)", L.r[i].key, L.r[i].otherinfo);
	printf("\n");
}

#define N 7
void main()
{
	RedType d[N] = { {49,1},{38,2},{65,3},{97,4},{76,5},{13,6},{27,7} };
	SqList l;
	int i;
	for (i = 0; i < N; i++)
		l.r[i + 1] = d[i];
	l.length = N;
	printf("排序前:\n");
	print(l);
	MergeSort(&l);
	printf("排序后:\n");
	print(l);
}

运行结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值