一、题目描述
Input Specification:
Output Specification:
Sample Input:
3 8
98 72 86 60 65 12 23 50
8 38 25 58 52 82 70 60
10 28 15 12 34 9 8 56
Sample Output:
Max Heap
50 60 65 72 12 23 86 98
Min Heap
60 58 52 38 82 70 25 8
Not Heap
56 12 34 28 9 8 15 10
二、解题思路
考察了堆的知识,首先我们要意识到堆其实是一个完全二叉树,所以我们对于这些结点的左右孩子的编号可以直接使用当前结点编号*2或者当前结点编号*2+1来获得。因为题目给的是层序遍历,那么我们就可以很容易将输入数据存入对应的结构体中。接着也按照层序遍历的方式来遍历这棵树,查看每个结点的孩子结点与当前结点键值,进行比较,判断是最大堆还是最小堆,最后后序遍历输出即可。
三、AC代码
#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn = 1010;
int N, M;
bool flag;
vector<int> ans;
struct Node
{
int key, lchild = -1, rchild = -1;
};
void postOrder(int root, Node* node) //二叉树的后序遍历
{
if(root == -1) return;
postOrder(node[root].lchild, node);
postOrder(node[root].rchild, node);
ans.push_back(node[root].key);
}
int main()
{
scanf("%d%d", &M, &N);
for(int i=0; i<M; i++)
{
Node node[maxn];
bool ismax = true, ismin = true;
ans.clear();
for(int j=1; j<=N; j++)
{
scanf("%d", &node[j].key);
if(2*j <= N) node[j].lchild = 2*j; //从1开始编号,完全二叉树的左孩子是偶数
if(2*j + 1 <= N) node[j].rchild = 2*j+1; //右孩子为奇数
}
for(int j=1; j<=N; j++)
{
if(node[j].lchild != -1)
{
if(ismin && node[j].key > node[node[j].lchild].key) ismin = false; //孩子比父亲结点的值要小,则不是最小堆
if(ismax && node[j].key < node[node[j].lchild].key) ismax = false; //孩子比父亲节点的值要大,则不是最大堆
}
if(node[j].rchild != -1) //右孩子同理
{
if(ismin && node[j].key > node[node[j].rchild].key) ismin = false;
if(ismax && node[j].key < node[node[j].rchild].key) ismax = false;
}
}
if(ismax || ismin) ismax ? printf("Max Heap\n") : printf("Min Heap\n"); //对应输出
else printf("Not Heap\n");
postOrder(1, node); //后序遍历存入元素
for(int j=0; j<ans.size(); j++)
j == 0 ? printf("%d", ans[j]) : printf(" %d", ans[j]);
printf("\n");
}
return 0;
}