问题描述:给定一个堆(数组),求根到每个叶节点的路径,和判断该堆是大堆、小堆还是不是堆。
解题思路:方法一,堆是一颗完全二叉树,叶节点只能可以从满的最底层开始,从叶子节点访问到根;方法二,先序遍历的应用,先访问右节点再访问左结点。判断的方法是一个一个结点的判断。
AC代码:
方法一
#include<iostream>
#include<algorithm>
#include<vector>
#include<cmath>
using namespace std;
#define MAX 1002
int N,arr[MAX];
vector<int>out;
int pow2(int n,int &x)//计算完全二叉树满层的最高一层的点数
{
int y=1;
while(y*2+1<=N){y=y*2+1;x*=2;}
return y;
}
void output()//输出out数组
{
for(int i=out.size()-1;i>=0;--i){
printf("%d",out[i]);
if(i)printf(" ");
}
printf("\n");
}
void print(int n,int x)
{
int y;
while(x--){
out.clear();
if(n*2+1<=N){
y=n*2+1;//3,6错误原因y=n*2+2;
while(y>0){out.push_back(arr[y]);y/=2;}
output();
out[0]=arr[n*2];
output();
}
else if(n*2<=N){
out.push_back(arr[n*2]);
y=n;
while(y>0){out.push_back(arr[y]);y/=2;}
output();
}else{
y=n;
while(y>0){
out.push_back(arr[y]);y/=2;
}
output();
}
--n;
}
}
int judge(int n)
{
bool flag=0;
if(arr[1]>arr[2])flag=1;//flag=1大堆,=0小堆
for(int i=1;i<=n;++i){
int x=i*2+1,y=i*2;
if(x<=N){
if(arr[x]<arr[i]&&arr[y]<arr[i]){
if(!flag)return -1;//不是堆
}else if(arr[x]>arr[i]&&arr[y]>arr[i]){
if(flag)return -1;
}else return -1;//其他情况,不是堆
}else if(y<=N){
if(arr[y]<arr[i]){
if(!flag)return -1;
}else if(arr[y]>arr[i]){
if(flag)return -1;
}
}
}
return flag;
}
int main()
{
freopen("test.txt","r",stdin);
scanf("%d",&N);
for(int i=1;i<=N;++i)scanf("%d",&arr[i]);
int x=1,n;
n=pow2(N,x);
print(n,x);
x=judge(n);
if(x==-1)printf("Not Heap");
else if(x==0)printf("Min Heap");
else printf("Max Heap");
return 0;
}
方法二
#include<iostream>
#include<vector>
using namespace std;
#define MAX 1005
vector<int>level,out;
int N;
void dfs(int v)
{
out.push_back(level[v]);
if(v*2+2<N)dfs(v*2+2);
else if(v*2+1<N){//右子树为空,左子树不为空,
dfs(v*2+1);
out.pop_back();//应该再弹出一个
return;
}else{//左右子树都为空,输出后弹出该点
for(int i=0;i<out.size();++i){
if(i)printf(" ");
printf("%d",out[i]);
}
printf("\n");
out.pop_back();
return;//结束
}
dfs(v*2+1);//访问左子树
out.pop_back();
}
int judge(int v)
{
if(v*2+2<N){
if(level[v]>level[v*2+2]){
if(level[v]>level[v*2+1])return 1;
return -1;
}else{
if(level[v]<level[v*2+1])return 0;
return -1;
}
}else{
if(level[v]>level[v*2+1])return 1;
return 0;
}
}
int main()
{
freopen("test.txt","r",stdin);
scanf("%d",&N);
level.resize(N);
for(int i=0;i<N;++i)scanf("%d",&level[i]);
dfs(0);
int x=judge(0);
if(x==-1)printf("Not Heap");
else{
for(int i=1;i*2+1<N;++i){
if(x!=judge(i)){
printf("Not Heap");
return 0;
}
}
if(x==1)printf("Max Heap");
else printf("Min Heap");
}
return 0;
}