题目翻译:
首先给定一个排序之前的序列,然后再给出一个进行到排序完成之前的一个“中间序列”,判断使用的是插入排序还是堆排序,并给出下一步的排序结果。
题解思路:
按照下面的思路展开:
- 首先求出第二个序列中从左向右第一个无序元素位置;
- 接着和a对比接下来的(因为如果是插入排序后边的是一样的),若一致,则是插入排序,只需要从无序位置和前面的比对找到合适位置插入即可;
- 如果不一致,证明是堆排序,要先从后向前遍历,找到首个小于堆首的元素位置(因为按题意堆排序是将最大值放到后面作为已排序区域),然后先对未排序区域执行以下操作:
- 将堆首元素(未排序区域的最大值)和未排序区域的最后一个元素(注意不是指最小值)交换位置;
- 然后重新平衡二叉树,使得二叉树重新为堆二叉树(根结点大于等于左右孩子结点)。
也可以参考1097
代码:
#include<bits/stdc++.h>
using namespace std;
int a[101], b[101];
void Next_step(int curnode, int len)
{
int k = curnode;
if (curnode * 2 <= len && b[curnode] < b[2 * curnode]) k = 2* curnode;
if (curnode * 2 + 1 <= len && b[k] < b[2 * curnode + 1]) k = 2* curnode + 1;
if (k != curnode)//左右结点大于目前结点
{
swap(b[k], b[curnode]);
Next_step(k, len);
}
}
int main()
{
int N;cin >> N;
for (int i = 1;i <= N;i++)cin >> a[i];
for (int i = 1;i <= N;i++)cin >> b[i];
int pos1;//b数组中第一个无序的位置
for (int i = 2;i <= N;i++)
if (b[i] > b[i + 1])
{
pos1 = i+1;
break;
}
int k = pos1;
while (b[k] == a[k] && k <= N)
k++;
if (k == N + 1)
{
cout << "Insertion Sort" << endl;
while (pos1 >= 1 && b[pos1] < b[pos1 - 1]) swap(b[pos1 - 1], b[pos1]), pos1--;//从无序位置进行下次插入排序
}
else
{
cout << "Heap Sort" << endl;
k = N;
while (b[k] >= b[1]) k--;
swap(b[1], b[k]);//将堆顶元素和从后向前第一个无序位置(未排序区域的最后一个位置,先将其换到根结点)交换
Next_step(1, k - 1);//使二叉树重新“有序”(根节点大于等于左右孩子结点的值)
}
cout << b[1];
for (int i = 2;i <= N;i++)
cout << " " << b[i];
}
坑点:
无