PATA1110 Complete Binary Tree

原题链接1110 Complete Binary Tree

题意

判断给定的二叉树是否是完全二叉树

思路

分析,什么样的树是完全二叉树非常好想,但是什么样的树不是完全二叉树,确实不太容易想全。其实就这么几种
在这里插入图片描述

第一种情况:存在这样的结点:左孩子为空,而右孩子不为空
第二种情况:已经出现过了存在左孩子、不存在右孩子的结点,又出现了这样的结点
第三种情况:已经出现过叶子结点,但是又出现了非叶结点
符合这三种情况之一即为非完全二叉树。代码可以针对这三种情况分别判断,我一开始只想起前两种情况来,提交时有两个测试点通不过。后面想起来还有第三种情况。
当然了,最好是将三种情况提取出公共的判断条件,这样代码里面只用判断公共条件即可。仔细观察可知,公共条件即为:在使用层次遍历序列进行遍历时,如果对于当前节点,其左孩子为空或者右孩子为空,并且在其前面已经出现了这种情况,则为非完全二叉树。
对于第一种情况来说,遍历到结点C时,当取其左孩子时,发现其左孩子为空,将标记为tag置为true,意味出现了少孩子的结点。当取到其右孩子时,发现其右孩子不空,但是已经出现缺少孩子的情况,所以,肯定不是完全二叉树。
其余两种情况类似。

#include <bits/stdc++.h>

using namespace std;

struct Node{
    int lchild,rchild;
    Node():lchild(-1),rchild(-1){}
}node[25];

int root = 0,last,n;
int father[25];
bool ans = true;

void BFS(int root){
    int cnt = 0;
    bool tag = false;
    queue<int> q;
    q.push(root);
    while(q.size()){
        int cur = q.front();
        q.pop();
        cnt++;
        if(cnt == n) last = cur;//数量累积到了n,当前cur即为最后一个结点

        if(node[cur].lchild != -1){//如果左孩子不空
            if(tag) ans = false;   //如果前面有缺孩子的结点,则非完全二叉树
            q.push(node[cur].lchild);
        }
        else tag = true;    //否则登记已经出现了缺少孩子的结点

        if(node[cur].rchild != -1){//如果右孩子不空
            if(tag) ans = false;//如果前面有缺孩子的结点,则非完全二叉树
            q.push(node[cur].rchild);
        }
        else tag = true; //否则登记已经出现了缺少孩子的结点
    }
}

int main()
{
    scanf("%d",&n);
    for(int i = 0;i < n;i++) father[i] = i;
    for(int fid = 0;fid < n;fid++){
        string l,r;
        cin>>l>>r;
        if(l != "-") {
            node[fid].lchild = stoi(l);
            father[stoi(l)] = fid;
        }
        if(r != "-"){
            node[fid].rchild = stoi(r);
            father[stoi(r)] = fid;
         }
    }

    while(root != father[root]) root = father[root];
    BFS(root);
    printf("%s %d",ans?"YES":"NO",ans?last:root);

    return 0;
}

2021/4/48更新
在做王道数据结构时,看到了书上的一个解法,补充一下
在这里插入图片描述
就是空结点NULL也要入队,出队时,遇到了NULL,则看后面的结点是否有非空结点如果有,则非CBT,否则是CBT。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值