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

分析:

       根据题目的意思,这个中间序列不是插入排序就是归并排序,而直接插入还是比较好判断的,我们只需要从有序数列之后的第一个位置开始判断两个数列元素是否相同。相同即为插入排序,否则为归并排序。

       此题是模拟插入和归并排序,并不需要直接写出插入和归并排序的算法,只要了解其原理即可。为了方便,这里用了sort进行排序。较难的问题是如何对归并排序进行下一轮排序,开始我想的是先找到其步长,后来发现会有许多麻烦的问题。就借鉴了其他人的做法,逐步模拟归并排序,直到与第二个数组相同,再进行一轮排序即可。

#include<iostream>
#include<algorithm>

using namespace std;

int a[100], b[100];
int N;

void Solve(){
	int i, j;
	for(i = 0; i < N - 1 && b[i] <= b[i + 1]; i++) ;
	for(j = i + 1; j < N && a[j] == b[j]; j++) ;
	if(j != N){
		cout << "Merge Sort" << endl;
		int step = 1, flag = 1;
		while(flag){
			flag = 0;
			for(i = 0; i < N; i++)
				if(a[i] != b[i]) flag = 1;
			step = step * 2;
			for(i = 0; i < N / step; i++)
				sort(a + i * step, a + (i + 1) * step);
			sort(a + i * step, a + N);
		}
	}else{
		cout << "Insertion Sort" << endl;
		sort(a, a + i + 2);
	}
	for(int m = 0; m < N; m++){
		if(m == 0) cout << a[m];
		else cout << ' ' << a[m];
	}
}

int main(){
	cin >> N;
	for(int i = 0; i < N; i++)
		cin >> a[i];
	for(int i = 0; i < N; i++)
		cin >> b[i];
	Solve();
}

 

### C++ 中插入排序和归并排序的实现 #### 插入排序 插入排序是一种简单直观的排序算法。该算法通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。 ```cpp void insertionSort(int arr[], int n) { for (int i = 1; i < n; ++i) { int key = arr[i]; int j = i - 1; while (j >= 0 && arr[j] > key) { arr[j + 1] = arr[j]; --j; } arr[j + 1] = key; } } ``` 这段代码展示了如何逐步将每个元素插入到已经排序的部分中[^1]。 #### 归并排序 归并排序采用分治法的思想,先递归地把数组分成两个子数组分别进行排序,再将这两个子数组合并成一个有序数组。 ```cpp void merge(int arr[], int l, int m, int r) { int n1 = m - l + 1; int n2 = r - m; int L[n1], R[n2]; for (int i = 0; i < n1; i++) L[i] = arr[l + i]; for (int j = 0; j < n2; j++) R[j] = arr[m + 1 + j]; int i = 0; int j = 0; int k = l; while (i < n1 && j < n2) { if (L[i] <= R[j]) { arr[k] = L[i]; i++; } else { arr[k] = R[j]; j++; } k++; } while (i < n1) { arr[k] = L[i]; i++; k++; } while (j < n2) { arr[k] = R[j]; j++; k++; } } void mergeSort(int arr[], int l, int r) { if (l < r) { int m = l + (r - l) / 2; mergeSort(arr, l, m); mergeSort(arr, m + 1, r); merge(arr, l, m, r); } } ``` 此部分实现了完整的归并排序逻辑,包括分割数组以及最终的合并操作[^4]。 这两段代码提供了两种不同的排序方式——插入排序适合较小规模的数据集;而归并排序则适用于更大范围内的应用场景,并且具有更稳定的性能表现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值