题目
https://pintia.cn/problem-sets/994805342720868352/problems/1071785408849047552
题意
打印该树所有从根节点到叶子节点的路径(先右后左),然后判断该树是大顶堆、小顶堆或者不是顶堆
思路
层序数组的特点(知者可跳)
首先我们要知道,按层序输出的数组有如下特点(下标从1开始),假设根节点的下标为root,那么它的左子节点的下标为root * 2,右子节点的下边为root * 2+1,下面我来举一个例子:
下标 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|---|
数值 | 6 | 3 | 8 | 1 | 5 | 4 | 9 | 0 | 2 | 4 |
画出来的树如下:
当root=1时(值为6),它的左子节点的下标为1 * 2=2(值为3),它的右子节点的下标为1 * 2+1=3(值为8)
当root=4时(值为1),它的左子节点的下标为4 * 2=8(值为0),它的右子节点的下标为4 * 2+1=9(值为2)
所以说,这就是层序顺序的数组所包含的规律,大家尽量掌握一下
详细思路
在了解到上述知识点后,我们按照层序的关系,将每一层与上一层比较,都满足大于等于的关系就是小顶堆,都满足小于等于的关系就是大顶堆,否则不是顶堆
然后我们利用dfs的基本思想,按层从右到左遍历数组,每一层对应最终数组ans的一个下标,当root*2>n
时(没有左子节点,表示自己就是叶子节点)直接输出即可
AC代码
#include<bits/stdc++.h>
using namespace std;
int n,a[1001],flag=0,cnt=0;
int ans[1001];
void dfs(int index,int root)
{
ans[index]=a[root];
if(root*2>n)
{
for(int i=1;i<=index;i++)
{
if(i==1) cout<<ans[i];
else cout<<" "<<ans[i];
}
cout<<endl;
return;
}
for(int i=root*2+1;i>=root*2;i--)
{
if(i>n) continue;
dfs(index+1,i);
}
}
int main()
{
cin>>n;
int i;
for(i=1;i<=n;i++)
cin>>a[i];
for(i=2;i<=n;i++)//判断小堆
if(a[i]<a[i/2]) break;
if(i==n+1) flag=1;
for(i=2;i<=n;i++)//判断大堆
if(a[i]>a[i/2]) break;
if(i==n+1) flag=2;
dfs(1,1);
if(flag==1) cout<<"Min Heap";
else if(flag==2) cout<<"Max Heap";
else cout<<"Not Heap";
}