1089 Insert or Merge (25 分)
题目大意
现给定原始序列和由某排序算法产生的中间序列,请你判断该算法是插入算法还是归并算法。首先在第1行中输出“Insertion Sort”表示插入排序、或“Merge Sort”表示归并排序;然后在第2行中输出用该排序算法再迭代一轮的结果序列。
基本思路
思路借鉴柳神,链接如下:
添加链接描述
先将ii指向中间序列中满足从左到右从小到大顺序的最后一个下标,再将jj指向从i+1开始第一个不满足a[jj]==b[jj]的下标,如果jj顺利到达了n,说明是插入排序,下一次迭代的序列是sort(a,a+ii+2);否则说明是归并排序,让序列a模拟归并排序的过程,当 当前序列和序列b相同时停止,再进行一次归并排序。输出中间序列下一次迭代后的序列。
代码
具体数据结构和详细思路的设计请看代码注释:
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
int n;
int a[100],b[100];
int ii,jj;//ii指向中间序列递增元素的最后一个的下标,jj指向从ii+1开始与原始序列不同的那个元素的下标
int main(){
cin>>n;
for(int i=0;i<n;i++) cin>>a[i];
for(int j=0;j<n;j++) cin>>b[j];
//找出ii、jj
for(ii=0;ii<n-1&&b[ii]<=b[ii+1];ii++);
for(jj=ii+1;jj<n&&a[jj]==b[jj];jj++);
//如果jj正好指向下标n,那么序列b是归并排序的中间序列
//求出序列b下一次迭代的序列,sort(b,b+ii+2),输出序列b
//否则序列b就是归并排序中间序列
//让序列a模拟归并排序的过程,当 当前序列和序列b完全相同时停止
//求出当前序列下一次迭代的序列,输出序列a
if(jj==n){
cout<<"Insertion Sort"<<endl;
sort(b,b+ii+2);//再进行一次迭代
for(int i=0;i<n;i++){
if(i!=0) cout<<" ";
cout<<b[i];
}
}else{
cout<<"Merge Sort"<<endl;
int k=1;//每次归并排序分组的大小。初始化为1
int flag=1;//当前序列是否需要进行归并排序,当当前序列和序列b完全相时置flag为0。初始化为1
while(flag){
//判断下一次循环是否还需要归并排序
//如果当前序列和序列b已经相同了,本次循环中的归并排序序列就能求出中间序列下一次迭代后的序列,下一个循环不需要排序了,所以flag为0
//否则当前的中间序列和序列b还没有完全相同,说明还需要进行归并排序,下一个循环还需要继续排序,置flag为1
flag=0;//下一次循环序列a不需要进行归并排序了
for(int i=0;i<n;i++){
if(a[i]!=b[i]){
flag=1;//下一次循环序列a还是要进行归并排序
break;
}
}
//进行本次循环的归并排序过程
k=k*2;
for(int i=0;i<n/k;i++){
sort(a+k*i,a+k*(i+1));
}
sort(a+(n/k)*k,a+n);
}
//输出序列a
for(int i=0;i<n;i++){
if(i!=0) cout<<" ";
cout<<a[i];
}
}
}