归并排序-源码

读周颜军; 王玉茹; 关伟洲. 数据结构 (21世纪高等教育计算机规划教材) (p. 216). 人民邮电出版社. 此书源码也是摘自此书

归并 排序( merge sort) 是 又一 类 不同 的 排序 方法。

 归并 排序 的 基本 思想: 将 已 有序 的 子 文件 进行 合并, 得到 完全 有序 的 文件。
 合并 时 只要 比较 各 有序 子 文件 的 第一个 记录 的 排序 码, 排序 码 最小 的 那个 记录 就是 排序 后的 第一个 记录; 取出 这个 记录, 然后 继续 比较 各个 子 文件 的 第一个 记录, 便可 找出 排序 后的 第二个 记录; 如此 继续 下去, 只要 经过 一 趟 扫描 就可以 得到 最终 的 排序 结果。
 对于 排序 码 任意 排列 的 待 排序 文件 进行 归并 排序 时, 可以 把 文件 中的 n 个 记录 看成 n 个子 文件。
每个 子 文件 只 包含 一个 记录, 显然 对于 个子 文件 来说 是 有序 的。
 但是, 要想 只 经过 一 趟 扫描 就 将 n 个子 文件 全部 归并 成 一个 有序 的 文件 显然 是 困难 的。
 通常, 可以 采用 两两 归并 的 方法, 即 每次 将 两个 子 文件 归并 成 一个 较大 的 有序 子 文件。
 第一 趟 归并 后, 得到 个 长度 为 2 的 有序 子 文件( 最后 一个 子 文件 长度 可 能为 1); 在此 基础上, 再进 行 以后 各 趟 的 归并, 每 经过 一 趟 后, 子 文件 的 个数 约 减少 一半, 而每 个子 文件 的 长度 约 增加 一倍。
 如此 反复, 直到 最后 一 趟 将 两个 有序 子 文件 归并 到 一个 文件 中,这时 整个 排序 工作 就 完成 了。

上述 的 归并 过程中, 每次 都是 将 两个 子 文件 合并 成 一个 较 大的 子 文件。 这种 归并 方法 称为 二路 归并( 2- way merge) 排序。 类似 地 也可以 采用 三路 归并 排序 或 多路 归并( multi - way merge) 排序。

源码如下:

void Merge(int x[],int y[], int low, int m, int high)
{
	int i,j,k,h;
	i = low-1;
	j = m ;
	k = low-1;
	cout << "low: " << low << " m: " << m << " high: " << high  << endl;
	while (i < m && j < high)
	{
		if (x[i] <= x[j])
		{
			//cout << "1 x[" << i << "]: " << x[i] << "  -> y[" << k << "]: " << endl;
			y[k++] = x[i++];
		}
		else
		{
			//cout << "2 x[" << j << "]: " << x[j] << "  -> y[" << k << "]: " << endl;
			y[k++] = x[j++];
		}
		
	} 
	if (i < m)
	{
		for (h = i; h < m; h++, k++)
		{
			//cout << "3 x[" << h << "]: " << x[h] << "  -> y[" << k << "]: " << endl;
			y[k] = x[h];
		}
	}
	if (j < high)
	{
		for (h = j; h < high; h++, k++)
		{
			//cout << "4 x[" << h << "]: " << x[h] << "  -> y[" << k << "]: " << endl;
			y[k] = x[h];
		}
	}
	
}

void MergePass(int x[], int y[], int n, int length)
{
	int i = 1, k;

	while (i <= n - 2 * length +1)
	{
		Merge(x, y, i, i + length - 1, i + 2 * length - 1);
		i = i + 2 * length;
	}
	
	if (i < n - length+1 )
	{
		cout << " start2 " << endl;
		Merge(x, y, i, i + length - 1, n);
		print(y, 15, 8);
		print(x, 15, 8);
		cout << " end2 " << endl;
	}
	else
	{
		cout << " start3  "<< i <<endl;
		for (k = i-1; k < n; k++)
		{
			y[k] = x[k];
		}
		print(y, 15, 8);
		print(x, 15, 8);
		cout << " end3 " << endl;
	}

}

void MergeSort(int  R[], int n)
{
	int  R1[25 + 1];
	int i=0, length = 1;
	memset(R1,-1,sizeof(R1));
	while (length < n) {
		MergePass(R, R1, n, length);
		length = 2 * length;
	
		if (length >= n) {
			for (i = 0;i < n;i++)
				R[i] = R1[i];
			
			return;
			// break;
		} 
		//print(R, 15, length);
		//print(R1, 15, length);
		//system("pause");
		MergePass(R1, R, n, length);
		length = 2 * length;
		
	}
}
int main(void) {
	//int x[12] = {8,1,3,2,6,5,9,7,8,4,0,4};
	//int x[12] = { 0,0,1,1,2,3,4,5,6,7,8,9 };
	//int x[23] = { 0,4,8,6,2,3,1,9,7,5,3,3,8,7,5,6,11,12,10,89,54,57,58 };
	int x[23] = { 0,4,8,6,2,3,1,9,7,5,3,3,8,7,5 };
	int b[25] ;
	memset(b, 0x00, sizeof(b));
	//mpsort(x, 12);
	//mpsort2(x, 12);
	//quitsort(x, 0, 11, 12);
	//gb1(x, b, 0, 8, 15);
	//gb2(x, b, 15, 1);
	//gb3(x, 15,b);
	MergeSort(x, 15);
	//MergeSort(x,23);
	print(x, 15, 8);
	//print(x, 23, 8);
	
	cout << endl<< "循环次数:" << gnum << endl;
	system("pause");
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值