题意
给定一个数组,和某排序的中间结果
判断是插入排序还是堆排序,并输出下一步操作后的结果
题解
- 判断是哪种排序,从样例中可以看到插入排序前面部分为部分有序,为后面的数字依旧按原来的排列,根据此入手,找到无序的部分将其和原来相比较,若相同则为插入排序,否则为堆排序
- 插入排序,找到下一个要操作的元素x,从后往前遍历,大于x则后移,最后再将x赋值到合适位置
- 堆排序,首要任务是读懂给的样例是什么意思。根据给定的数组,从最后一个非叶节点开始调整建立大顶堆(建堆),然后将堆顶和最后一个元素交换,并调整(排序)。
源码
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
int main(){
int n;
cin>>n;
int arr[105],par[105];
memset(arr,-1,sizeof(arr));
memset(par,-1,sizeof(par));
for(int i=1;i<=n;i++){
int x;cin>>x;
arr[i]=x;
}
for(int i=1;i<=n;i++){
int x;cin>>x;
par[i]=x;
}
//判断哪种类型
int kind=1;
int index=-1;
for(int i=1;i<=n;i++){
if(par[i]<par[i-1]){
index=i;
break;
}
}
for(int i=index;i<=n;i++){
if(arr[i]!=par[i]){
kind=0; break;
}
}
if(kind){
cout<<"Insertion Sort"<<endl;
int pos,target;
for(int i=1;i<=n;i++){
if(par[i]<par[i-1]){
pos=i;
target=par[i];
break;
}
}
int i;
for(i=pos;i>=1&&par[i-1]>target;i--){
par[i]=par[i-1];
}
par[i]=target;
for(i=1;i<n;i++){
cout<<par[i]<<" ";
}
cout<<par[n]<<endl;
}else{
cout<<"Heap Sort"<<endl;
sort(arr,arr+n+1);
int pos;
for(int i=n;i>=1;i--){
if(arr[i]!=par[i]){
pos=i;
break;
}
}
int t=par[pos];
par[pos]=par[1];
par[1]=t;
int finish=0;
int change=1;
pos--;
while(!finish){
int l=change*2;
int r=change*2+1;
if(l>pos) break; //l越界,说明结束
if(r>pos){ //l刚好在界上
r=0; //par[0]==-1
}else{ //全都在界内
if(par[l]<par[change]&&par[r]<par[change]){
break;
}
}
//堆顶与最后元素交换
int z=par[l]>par[r]?l:r;
t=par[z];
par[z]=par[change];
par[change]=t;
change=z;
}
for(int i=1;i<n;i++){
cout<<par[i]<<" ";
}
cout<<par[n]<<endl;
}
return 0;
}