返回目录![在这里插入图片描述](https://img-blog.csdnimg.cn/20200415104639994.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ExOTIwOTkzMTY1,size_16,color_FFFFFF,t_70)
题意
给出一个初始序列,可以对它使用插入排序或堆排序法进行排序。现在给出一个序列,试判断它是由插入排序还是堆排序产生的,并输出下一步将会产生的序列。
样例(可复制)
10
3 1 2 8 7 5 9 4 6 0
1 2 3 7 8 5 9 4 6 0
//output
Insertion Sort
1 2 3 5 7 8 9 4 6 0
10
3 1 2 8 7 5 9 4 6 0
6 4 5 1 0 3 2 7 8 9
//output
Merge Sort
1 2 3 8 4 5 7 9 0 6
注意点
- 本题与B1035/A1089非常类似,需要直接模拟插入排序和堆排序的每一步过程。拥有同样一个陷阱,初始序列不参与与中间序列的比较
- 插入部分代码排序考虑直接用sort
- 注意堆排序插入元素从数组最后一个开始,从后往前插入
- equal是C++标准库中函数,如果两个序列对应位置上的元素都相等,则返回true
# include<bits/stdc++.h>
using namespace std;
int n,A[105],start[105],target[105];
void down(int index,int n){//堆排序下滤
int t=A[index];
while(2*index+1<n){//有儿子结点
int child=2*index+1;
if(child+1<n&&A[child]<A[child+1])//找到值比较大的儿子结点
++child;
if(A[child]>t){//如果儿子结点的值大于父亲结点的值
A[index]=A[child];//儿子结点的值移动到父亲结点
index=child;
}else
break;
}
A[index]=t;
}
int main(){
cin>>n;
for(int i=0;i<n;i++)scanf("%d",&start[i]);
for(int i=0;i<n;i++)scanf("%d",&target[i]);
memcpy(A,start,sizeof(start));//将原始序列拷贝给A数组
bool f=false;
for(int i=1;i<n;i++){//进行插入排序
sort(A,A+i+1);//直接使用sort
if(equal(A,A+n,target)){
f=true;
printf("Insertion Sort\n");
sort(A,A+i+2);//直接使用sort
break;
}
}
if(!f){//是堆排序
printf("Heap Sort\n");
memcpy(A,start,sizeof(start));
for(int i=n/2;i>=0;i--)//将前一半元素进行下滤
down(i,n);
for(int i=n-1;i>0;i--){
swap(A[i],A[0]);
down(0,i);
if(equal(A,A+n,target)){
swap(A[i-1],A[0]);//进行下一趟排序
down(0,i-1);//进行下一趟排序
break;
}
}
}
for(int i=0;i<n;i++){
printf("%d",A[i]);
if(i!=n-1) printf(" ");
}
return 0;
}