1098 Insertion or Heap Sort (25 分)
题意
给出一个初始序列,可以对它使用插入排序或堆排序法进行排序。现在给出一个序列,试判断它是由插入排序还是堆排序产生的,并输出下一步将会产生的序列。
思路
本题与A1089非常类似,需要直接模拟插入排序和堆排序的每一步过程。
具体做法为:先进行插入排序,如果执行过程中发现与给定序列吻合,那么说明是插入排序,计算出下一步将会产生的序列后结束算法;如果不是插入排序,那么一定是堆排序,模拟堆排序的过程,如果执行过程中发现与给定序列吻合,那么计算出下一步将会产生的序列后结束算法。
注意点
- 本题参考代码中插入部分直接用sort实现,可以节省编码时间。
- 和A1089一样的陷阱:初始序列不参与比较是否与目标序列相同(也就是说,题目中说的中间序列是不包括初始序列的)。
- 要求从小到大排序,因此用大根堆,每次把最大值放到序列结尾。
const int N=1010;
int a[N],b[N];
int heap[N];
int n;
bool isSame(int a[])
{
for(int i=1;i<=n;i++)
if(a[i] != b[i])
return false;
return true;
}
//bool InsertSort()
//{
// bool ok=false;
// for(int i=2;i<=n;i++)
// {
// if(isSame(a) && i != 2) ok=true;
// int t=a[i];
// int j=i;
// while(j && a[j-1] > t)
// {
// a[j]=a[j-1];
// j--;
// }
// a[j]=t;
//
// if(ok) return true;
// }
// return false;
//}
bool InsertSort()
{
bool ok=false;
for(int i=2;i<=n;i++)
{
if(isSame(a) && i != 2) ok=true;
//插入部分直接用sort代替
sort(a+1,a+i+1);
if(ok) return true;
}
return false;
}
void down(int u,int n)
{
int j=u*2;
while(j <= n)
{
if(j<n && heap[j] < heap[j+1])
j++;
if(heap[u] < heap[j])
{
swap(heap[u],heap[j]);
u=j;
j=u*2;
}
else
break;
}
}
void CreateHeap()
{
for(int i=n/2;i>=1;i--)
down(i,n);
}
void HeapSort()
{
CreateHeap();
bool ok=false;
for(int i=n;i>=1;i--)
{
if(isSame(heap) && i != n) ok=true;
swap(heap[1],heap[i]);
down(1,i-1);
if(ok) break;
}
}
void print(int a[])
{
for(int i=1;i<=n;i++)
if(i>1) cout<<' '<<a[i];
else cout<<a[i];
cout<<endl;
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i],heap[i]=a[i];
for(int i=1;i<=n;i++) cin>>b[i];
if(InsertSort())
{
puts("Insertion Sort");
print(a);
}
else
{
puts("Heap Sort");
HeapSort();
print(heap);
}
//system("pause");
return 0;
}