【InsertionSort_MergeSort——PTAques的文件名】
7-1 插入排序还是归并排序
根据维基百科的定义:
插入排序是迭代算法,逐一获得输入数据,逐步产生有序的输出序列。每步迭代中,算法从输入序列中取出一元素,将之插入有序序列中正确的位置。如此迭代直到全部元素有序。
归并排序进行如下迭代操作:首先将原始序列看成 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
思路:实现insertion和merge,每一次迭代和B作一次比较,
如果相等则做标记,再走一轮则停止。【会改变输入的A,所以直接return,但是最先构造两个A,以防验证两次。】
如果不相等,则ans=-1不变,走merge。
merge算法借鉴网上不是很懂,其余注释写在文章中【有一个错误MD找了好TM久】。
#include <iostream>
using namespace std;
//int C[100]={0};
int ans=-1;
void swap(int* A,int j ,int i){
int temp=A[j];
A[j]=A[i];
A[i]=temp;
}
void insertion(int* A, int* B, int n){ //为了每次写完都比较,所以每次迭代完都比较一次
int flag2=0;
for (int i=1;i<n;i++){ //第0个可以不用排
int flag=0;
for (int j=i;j>0;j--){
if (A[j]<A[j-1])
swap(A,j,j-1);
}
for (int i=0;i<n;i++){
if(A[i]!=B[i]){
flag=1;
break;
}
}
if (flag2==1){
// for (int i=0;i<n;i++)
// C[i] = A[i];
return; //记录了下一轮,该程序结束
}
if (flag==0) {
ans=1;
flag2=1;//再进行下一轮
}
}
}
void mergeSortHelper(int* A, int head1, int head2, int tail2){
int tail1 = head2-1, index=0,len=tail2-head1+1,start=head1;
int temp[len];
while(head1 <= tail1 || head2 <= tail2){
if (head1 > tail1)
temp[index++]=A[head2++];
else if(head2 > tail2)
temp[index++]=A[head1++];
else{
if(A[head1] <= A[head2])
temp[index++]=A[head1++];
else
temp[index++]=A[head2++];
}
}
for (int i=0;i<len;i++)
A[start+i]=temp[i];
}
void merge(int* A, int* B, int n){ //迭代法的归并排序,
//首先将原始序列看成 N 个只包含 1 个元素的有序子序列,然后每次迭代归并两个相邻的有序子序列,直到最后只剩下 1 个有序的序列。
//网上借鉴,不是很懂????
int flag2=0;
for (int step=1; step<=n; step <<= 1){
int flag=0;
int offset = step+step;
for (int index=0;index<n;index+=offset)
mergeSortHelper(A,index,min(index+step,n-1),min(index+offset-1,n-1));
for(int i=0;i<n;i++){
if (A[i]!=B[i]){
flag=1;
break;
}
}
// for (int i=0;i<n-1;i++)
// cout<<A[i]<<" ";
// cout<<A[n-1]<<endl;
if (flag2==1){
return; //又迭代了一轮,故停止。A在此过程中是一直被改变的
}
if (flag==0){ //操!!!这里一直写的1,怪不得是错的。只要不等就认定了。
flag2=1; //在这里相等了
}
}
}
int main()
{
int N;
cin >> N;
int A[N],B[N];
int A1[N];
for (int i=0;i<N;i++){
cin >> A[i];
A1[i] = A[i];
}
for (int i=0;i<N;i++)
cin >> B[i];
insertion(A1,B,N);
if (ans!=-1){
cout<<"Insertion Sort"<<endl;
for (int i=0;i<N-1;i++)
cout<<A1[i]<<" ";
cout<<A1[N-1]<<endl;
}
else{//肯定就时merge的情况
merge(A,B,N);
cout<<"Merge Sort"<<endl;
for (int i=0;i<N-1;i++)
cout<<A[i]<<" ";
cout<<A[N-1]<<endl;
}
// int A[9]={8,6,4,2,9,1,0,-2,5};
// int B[9]={0};
// merge(A,B,9);
// for (int i=0;i<7;i++)
// cout<<A[i]<<" ";
}