1035 插入与归并

1035 插入与归并 (25 分)

根据维基百科的定义:

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

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

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

输入格式:

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

输出格式:

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

题目链接

 题目分析:

坑点1:这个题的归并和我们常见的归并不大相同,常见的归并是二分再二分直到最小的一个数,再归并,分治思想,有点深度优先的感觉。此题的归并是length from 1 to n,每次让数组相邻length长度的数字内部有序,直到length=n时全部有序。

解题思路:

1、使用排除法判断归并还是插入,很明显插入排序前半部分有序,后半部分与原始数组相同

2、qsort的使用,可指定数组从某个位置开始到length长度的数组内排序,insert排序只需并原有序长度+1即可

3、merge用qsort比较巧妙,一个for循环控制length长度,内置两个for循环,一个用于比较是否相等跳出for循环,另外一个进行一轮归并排序

qsort参考链接

非递归版归并排序参考链接

#include<bits/stdc++.h>
#define MAX 100010
using namespace std;
int a[MAX],b[MAX],n;
int cmp(const void *m,const void *n)
{
	return *(int *)m-*(int *)n;
}
bool isinsert()
{
	int i,length;
	for(i=0;i<n-1&&b[i]<=b[i+1];i++);//i<n-1注意数组越界 
	length=i+2;//被坑了呜呜呜  +2是因为下标从0开始并且排序的数目并之前+1 
	for(i++;i<n&&a[i]==b[i];i++);
	if(i<n)
		return 1;//排除法确定并非插入排序  而是归并排序 
	cout<<"Insertion Sort"<<endl;
	qsort(a,length,sizeof(int),cmp);
	return 0;
}
void merge()
{
	cout<<"Merge Sort"<<endl;
	int i,j,length; 
	for(i=0,length=1;i<n&&length<=n;length*=2)
	{
		for(i=0;i<n&&a[i]==b[i];i++);//保证在和第二行匹配上后  再经过一次排序 即可跳出循环
		for(j=0;j<n/length;j++)
			qsort(a+j*length,length,sizeof(int),cmp);
		qsort(a+j*length,n%length,sizeof(int),cmp);//n%length保证数组不会越界 
	}
}
int main()
{
//	int n;
	cin>>n;
	for(int i=0;i<n;i++)
		cin>>a[i];
	for(int i=0;i<n;i++)
		cin>>b[i];
	if(isinsert())
		merge();
	for(int i=0;i<n;i++)
	{
		cout<<a[i];
		if(i!=n-1)
			cout<<" ";
	}
}

### 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、付费专栏及课程。

余额充值