PAT甲级1098Insertion or Heap Sort
题目链接
https://pintia.cn/problem-sets/994805342720868352/problems/994805368847187968
题解
题目要求
- 给定一个序列,及用某种排序方法经过几次迭代后的结果,请指出用了什么排序方法。(升序)
- 输入
- N:正整数,不超过100,给定序列中元素的个数
- 给定序列:N个整数
- 未完全排序的序列
- 输出
- 输出是堆排序还是插入排序
- 输出该排序算法下一步迭代的结果
解题思路
-
插入排序特征:序列分成左右两部分,左半部分是从小到大,右半部分是原序列。据此可以检测是否是插入排序,否则是堆排序。
-
堆排序特征:序列分成左右两部分,左半部分是大顶堆,右半部分是从小到大。
步骤如下:
- 将序列[1,N]构建成大顶堆(最终得到升序序列)
- 将堆顶元素(值最大)与末尾元素交换
- 将序列[1,N-1]构建/调整为大顶堆(重复步骤1、2)
代码
// Problem: PAT Advanced 1098
// URL: https://pintia.cn/problem-sets/994805342720868352/problems/994805368847187968
// Tags: 堆 排序 堆排序 插入排序 完全二叉树
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
void max_heapify(vector<int>& b, int start, int end){
int father = start, child = father * 2; // 结点从1开始编号
while (child <= end){
if (child + 1 <= end && b[child] < b[child + 1]) // 取值较大的子结点
child++;
if (b[father] >= b[child]) //如果父结点大于子结点,则不需调整,函数结束
break;
swap(b[father], b[child]);
father = child;
child = father * 2;
}
}
int main()
{
int n;
vector<int> a(n+1), b(n+1);
scanf("%d", &n);
for (int i = 1; i <= n; i++){
scanf("%d", &a[i]);
}
for (int i = 1; i <= n; i++){
scanf("%d", &b[i]);
}
int p = 2;
while (p <= n && b[p] >= b[p - 1])
p++;
int index = p;
while (p <= n && a[p] == b[p])
p++;
if (p == n+1){
printf("Insertion Sort\n");
int key = b[index];
p = index - 1;
while (p > 0 && b[p] >= b[index])
p--;
for (int i = index; i > p + 1; i--)
b[i] = b[i-1];
b[p+1] = key;
}
else{
printf("Heap Sort\n");
p = n;
while (p > 2 && b[p] >= b[1])
p--;
swap(b[1], b[p]);
max_heapify(b, 1, p - 1);
}
printf("%d", b[1]);
for (int i = 2; i <= n; i++)
printf(" %d", b[i]);
return 0;
}
参考链接
https://blog.csdn.net/liuchuo/article/details/52252172
https://www.cnblogs.com/chengxiao/p/6129630.html
https://baike.baidu.com/item/堆排序/2840151
作者:@臭咸鱼
转载请注明出处:https://www.cnblogs.com/chouxianyu/
欢迎讨论和交流!