题目链接:点击进入
题目
题意
大概就是给一棵完全二叉树,然后让你输出从根节点到所有叶节点的路径,从右往左输出。然后判断该树是大顶堆、小顶堆或者啥也不是。
思路
输出所有根节点到叶子节点的路径,可以将所有叶子节点存下来(先存右边的,这样输出就是从右边开始的了),有几个叶子节点,就输出几条路径。用vector保存每条路上的节点。由于完全二叉树的特点,根节点到叶子节点的路径,就是从叶子节点的编号,不断/2,直到等于1(根节点)的过程中,编号的所有取值。(大概可以理解为,每个点都由它的父亲节点走来,它的父亲节点编号=儿子节点编号/2)
通过push和pop回溯,维护路径,index <= n是对只有左叶节点没有右叶节点的点特判
2.判断是否为堆:从第二个节点开始遍历,如果比父节点小,就不是小顶堆,如果比父节点大,就不是大顶堆~
代码
#include<iostream>
#include<map>
#include<vector>
#include<cstring>
using namespace std;
const int maxn=1e5+10;
int n,a[1010],flag;
vector<int>v,path[1010];
void dfs(int p)
{
if(p*2>n)
{
v.push_back(p);
return ;
}
if(p*2+1<=n) dfs(p<<1|1);
if(p*2<=n) dfs(p<<1);
}
void dfs1(int p)
{
int l=p<<1;
int r=p<<1|1;
if(l>n&&r>n) return ;
if(l<=n&&r<=n)
{
if(a[l]>a[p]||a[r]>a[p])
{
flag=1;
return ;
}
dfs1(l);
dfs1(r);
}
else if(l<=n)
{
if(a[l]>a[p])
{
flag=1;
return ;
}
dfs1(l);
}
else if(r<=n)
{
if(a[r]>a[p])
{
flag=1;
return ;
}
dfs1(r);
}
}
void dfs2(int p)
{
int l=p<<1;
int r=p<<1|1;
if(l>n&&r>n) return ;
if(l<=n&&r<=n)
{
if(a[l]<a[p]||a[r]<a[p])
{
flag=1;
return ;
}
dfs2(l);
dfs2(r);
}
else if(l<=n)
{
if(a[l]<a[p])
{
flag=1;
return ;
}
dfs2(l);
}
else if(r<=n)
{
if(a[r]<a[p])
{
flag=1;
return ;
}
dfs2(r);
}
}
int main( )
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
dfs(1);
for(int i=0;i<v.size();i++)
{
int p=v[i];
path[i].push_back(p);
while(p/2)
p/=2,path[i].push_back(p);
}
for(int i=0;i<v.size();i++)
{
int len=path[i].size();
for(int j=len-1;j>=0;j--)
{
if(j==0)
cout<<a[path[i][j]]<<endl;
else
cout<<a[path[i][j]]<<' ';
}
}
flag=0;
dfs1(1);
if(!flag)
{
cout<<"Max Heap"<<endl;
return 0;
}
flag=0;
dfs2(1);
if(!flag)
cout<<"Min Heap"<<endl;
else
cout<<"Not Heap"<<endl;
return 0;
}