1035. 插入与归并(25)

本文介绍了一个编程问题,通过给定的原始序列和中间序列来判断使用的是插入排序还是归并排序,并输出下一轮排序结果。提供了完整的C语言代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1035. 插入与归并(25)

时间限制
200 ms
内存限制
65536 kB
代码长度限制
8000 B
判题程序
Standard
作者
CHEN, Yue

题目链接:http://www.patest.cn/contests/pat-b-practise/1035

根据维基百科的定义:

插入排序是迭代算法,逐一获得输入数据,逐步产生有序的输出序列。每步迭代中,算法从输入序列中取出一元素,将之插入有序序列中正确的位置。如此迭代直到全部元素有序。

归并排序进行如下迭代操作:首先将原始序列看成N个只包含1个元素的有序子序列,然后每次迭代归并两个相邻的有序子序列,直到最后只剩下1个有序的序列。

现给定原始序列和由某排序算法产生的中间序列,请你判断该算法究竟是哪种排序算法?

输入格式:

输入在第一行给出正整数N (<=100);随后一行给出原始序列的N个整数;最后一行给出由某排序算法产生的中间序列。这里假设排序的目标序列是升序。数字间以空格分隔。

输出格式:

首先在第1行中输出“Insertion Sort”表示插入排序、或“Merge Sort”表示归并排序;然后在第2行中输出用该排序算法再迭代一轮的结果序列。题目保证每组测试的结果是唯一的。数字间以空格分隔,且行末不得有多余空格。

输入样例1:
10
3 1 2 8 7 5 9 4 6 0
1 2 3 7 8 5 9 4 6 0
输出样例1:
Insertion Sort
1 2 3 5 7 8 9 4 6 0
输入样例2:
10
3 1 2 8 7 5 9 4 0 6
1 3 2 8 5 7 4 9 0 6
输出样例2:
Merge Sort
1 2 3 8 4 5 7 9 0 6
 
 
#include <stdio.h>
int Insertion(int* data, int* sorting, int n) {
	int j;
	for(int i = 1; i < n; ++i) {
		int tmp = data[i];
		for(j = i; j > 0 && data[j - 1] > tmp; --j)
			data[j] = data[j - 1];
		data[j] = tmp;
		for(j = 0; j < n; ++j)			//判断是否与sorting中元素一一对应
			if(data[j] != sorting[j])
				break;
		if(j == n) {	//如果是插入排序,输出下一轮排序的值并返回1
			tmp = data[i + 1];	//开始下一轮排序
			for(j = i + 1; j > 0 && data[j - 1] > tmp; --j)
				data[j] = data[j - 1];
			data[j] = tmp;
			printf("Insertion Sort\n");	//输出排序后的结果
			for(j = 0; j < n; ++j) {	
				if(j)
					printf(" ");
				printf("%d", data[j]);
			}
			return 1;	//返回1表示是插入排序
		}
	}
	return 0;	//返回0表示不是插入排序
}
void MergeSort(int* data, int* tmp, int* sorting, int n) {	//归并排序的迭代实现
	int step, lBegin, lEnd, rBegin, rEnd;
	for(step = 1; step < n; step *= 2) { //步长,1、2、4、8……
		for(lBegin = 0; lBegin < n - step; lBegin = rEnd + 1) {		//少于等于一个步长的元素不需要排序
			rBegin = lBegin + step;
			lEnd = rBegin - 1;
			rEnd = lEnd + step;
			if(rEnd > n - 1)	//归并的右半块不超过数组边界
				rEnd = n - 1;
			int k = 0;			//暂存数组的右边界下标
			while(lBegin <= lEnd && rBegin <= rEnd)
				tmp[k++] = data[lBegin] < data[rBegin] ? data[lBegin++] : data[rBegin++];
			while(lBegin <= lEnd)
				tmp[k++] = data[lBegin++];
			while(rBegin <= rEnd)
				tmp[k++] = data[rBegin++];
			while(k > 0)		//rBegin、k分别指向data、tmp数组最后一个数据的右一个
				data[--rBegin] = tmp[--k];
		}
		int i;
		for(i = 0; i < n; ++i)		//判断是否与sorting的数据一一对应
			if(data[i] != sorting[i])
				break;
		if(i == n) {		//如果是归并排序,继续下轮归并并输出
			step *= 2;
			for(lBegin = 0; lBegin < n - step; lBegin = rEnd + 1) {
				rBegin = lBegin + step;
				lEnd = rBegin - 1;
				rEnd = lEnd + step;
				if(rEnd > n - 1)
					rEnd = n - 1;
				int k = 0;
				while(lBegin <= lEnd && rBegin <= rEnd)
					tmp[k++] = data[lBegin] < data[rBegin] ? data[lBegin++] : data[rBegin++];
				while(lBegin <= lEnd)
					tmp[k++] = data[lBegin++];
				while(rBegin <= rEnd)
					tmp[k++] = data[rBegin++];
				while(k > 0)
					data[--rBegin] = tmp[--k];
			}
			printf("Merge Sort\n");
			for(int j = 0; j < n; ++j) {
				if(j)
					printf(" ");
				printf("%d", data[j]);
			}
			return;
		}
	}
}
int main() {
	freopen("in", "r", stdin);
	int n;
	scanf("%d", &n);
	int data[100], sorting[100];
	for(int i = 0; i < n; ++i)
		scanf("%d", &data[i]);
	for(int i = 0; i < n; ++i)
		scanf("%d", &sorting[i]);
	int tmp[100];			//备份原始数组用于两个排序,同时用于归并排序的临时数组
	for(int i = 0; i < n; ++i)
		tmp[i] = data[i];
	if(!Insertion(tmp, sorting, n))		//如果确定不是插入,则开始检查归并排序
		MergeSort(data, tmp, sorting, n);

	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值