2016.3.12的浙大PAT甲级第三题。
题目大意:
就是给出一颗二叉树,问这个是不是一颗完全二叉树,完全二叉树就是除最后一层外,每一层上的节点数均达到最大值,在最后一层上只缺右边的若干节点的树。
解题思路:
先找到树的根节点,然后用类似广搜的方法,确保前一层都放满后再去找下一层。具体做法是用一个队列存放某一层的节点,用cnt表示当前已经遍历过节点的数量,一旦cnt==n(树的节点总数),则表示是完全二叉树,否则在cnt==n之前一旦出现某个节点没孩子的情况,就不是完全二叉树了。
代码:
#include<cstdio>
#include<cstring>
#include<queue>
#include<iostream>
using namespace std;
struct node
{
int left,right;//节点左孩子和右孩子的标号
}p[25];
int pre[25];//节点的父亲节点标号,用于确定根节点
char str1[5],str2[5];
int main()
{
int n,i,root;
scanf("%d",&n);
memset(pre,-1,sizeof(pre));
for(i=0;i<n;i++)
{
scanf("%s%s",str1,str2);
if(str1[0]=='-')
p[i].left=-1;
else
{
sscanf(str1,"%d",&p[i].left);
pre[p[i].left]=i;
}
if(str2[0]=='-')
p[i].right=-1;
else
{
sscanf(str2,"%d",&p[i].right);
pre[p[i].right]=i;
}
}
if(n==1)
{
puts("YES 0");
return 0;
}
for(i=0;i<n;i++)
if(pre[i]==-1)
{
root=i;
break;
}
queue<int>q;
int cnt=1,flag=0,tmp;//cnt是当前遍历过的节点个数
q.push(root);
while(!q.empty())
{
tmp=q.front();
q.pop();
if(p[tmp].left==-1)
{
flag=1;
break;
}
q.push(p[tmp].left);
cnt++;
if(cnt==n)
break;
if(p[tmp].right==-1)
{
flag=1;
break;
}
q.push(p[tmp].right);
cnt++;
if(cnt==n)
break;
}
if(flag)
printf("NO %d\n",root);
else
printf("YES %d\n",p[tmp].right==-1?p[tmp].left:p[tmp].right);//这个tmp保留了最后一个节点的父亲节点
return 0;
}