首页 > 其他分享 >判断完全二叉树

判断完全二叉树

时间:2023-04-09 17:44:55浏览次数:44  
标签:判断 val int Tree 完全 right 二叉树 root left

1. 题目链接

天梯赛真题 -- 是否是完全二叉搜索树

2. 根据节点编号判断(better)

借鉴自这里

规定根节点的编号为 \(1\),左孩子节点编号为 \(left\),右孩子节点编号为 \(right\),父节点的节点编号为 \(fa\),则有:
\(left = fa << 1\)
\(right = fa << 1 | 1\)
由于完全二叉树的节点编号是递增的,因此它的最大的节点编号一定等于节点的个数。所以说,我们可以根据这一性质,简单的通过一个 \(dfs\) 就可以判断是否是完全二叉树。

// 建立完全二叉树 + 判断二叉完全树
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>

using namespace std;

const int N = 23;

typedef struct searchTree_t {
    int val;
    searchTree_t *left;
    searchTree_t *right;
    searchTree_t(int _val) : val(_val), left(nullptr), right(nullptr) {}
} Tree;

int n;
Tree *q[21];

// 左子树大,右子树小
void insert(Tree *&root, int x)
{
    if(root == nullptr)    
    {
        Tree *newNode = new Tree(x);
        root = newNode;
        return ;
    }
    if(x < root->val)  insert(root->right, x);
    else    insert(root->left, x);
}

Tree* init()
{
    Tree *root = nullptr;
    cin >> n;
    for(int i = 0; i < n; i ++ )
    {
        int x;  cin >> x;
        insert(root, x);
    }
    return root;
}

// 层次遍历
void bfs(Tree *root)
{
    if(root == nullptr) return ;
    int hh = 0, tt = -1;
    q[ ++ tt ] = root;
    while(hh <= tt)
    {
        auto t = q[ hh ++ ];
        if(t->left)     q[ ++ tt ] = t->left;
        if(t->right)    q[ ++ tt ] = t->right;
    }
    for(int i = 0; i < n; i ++ )
        cout << q[i]->val << " \n"[i == n - 1];
}

// dfs 得到最大的节点编号
int max_node;
void dfs(Tree *&root, int k)
{
    if(root == nullptr) return ;
    if(max_node > n)    return ;    // 剪枝 && 防溢出
    
    max_node = max(max_node, k);
    if(root->left)  dfs(root->left, k << 1);
    if(root->right) dfs(root->right, k << 1 | 1);
}

void solve()
{
    Tree *t = init();
    /*====== question1 ========*/
    bfs(t);
    /*====== question2 ========*/
    max_node = 1;
    dfs(t, 1);
    if(max_node == n) puts("YES");
    else    puts("NO");
}

int main()
{
    solve();
    return 0;
}

3. 根据完全二叉树的性质判断

看一下这里判断是否是完全二叉树在看一下上面的,高下立判了!
光从代码上看,上面的 \(dfs\) 仅仅 \(11\) 行,而下面的类似于“模拟”用了 \(30\) 行,并且代码量大就意味着,出错了不好调 \(bug\),理解不深刻的话还可能写不出来等等问题。
不过,这种方法仍然值得掌握!

#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
 
using namespace std;
 
int n, a[100];
typedef struct tree{
    int val;
    struct tree *left, *right;
}TreeNode, *Tree;
 
void add(Tree &t, int val)
{
    if(t == NULL)   
    {
        Tree s = new TreeNode;
        s->val = val;
        s->left = s->right = NULL;
        t = s;
    }
    else
    {
        if(val > t->val)    add(t->left, val);
        else add(t->right, val);
    }
}
 
void levelPrint(Tree &t)
{
    if(t == NULL)   return ;
    
    vector<int> v;
    queue<Tree> q;
    
    q.push(t);
    while(q.size())
    {
        auto t = q.front();
        q.pop();
        v.push_back(t->val);
        if(t->left) q.push(t->left);
        if(t->right)    q.push(t->right);
    }
    
    for(int i = 0; i < v.size(); i ++ )
    {
        cout << v[i];
        if(i != v.size() - 1)   cout << " ";
    }
    cout << endl;
}
 
bool check(Tree &t)
{
    if(t == NULL)   return false;
    
    queue<Tree> q;
    q.push(t);
    while(q.size())
    {
        auto t = q.front();
        q.pop();
        if(t->left && t->right)
        {
            q.push(t->left);
            q.push(t->right);
        }
        else if(!t->left && t->right)   return false;
        else if(!t->right)
        {
            if(t->left) q.push(t->left);
            while(q.size())
            {
                t = q.front();
                if(!t->left && !t->right)   q.pop();
                else    return false;
            }
            return true;
        }
    }
    return true;
}
 
int main()
{ 
    Tree t = NULL;
    cin >> n;
    for(int i = 0; i < n; i ++ )
    {
        int v;
        cin >> a[i];
    }
    for(int i = 0; i < n; i ++ )    add(t, a[i]);
    levelPrint(t);
    
    bool flag = check(t);
    if(flag)   cout << "YES" << endl;
    else    cout << "NO" << endl;
    return 0;
}

标签:判断,val,int,Tree,完全,right,二叉树,root,left
From: https://www.cnblogs.com/ALaterStart/p/17300674.html

相关文章

  • 14.6二叉树的层序遍历实战
    function.h////Createdby93757on2023/3/21.//#ifndefINC_1_TREE_FUNCTION_H#defineINC_1_TREE_FUNCTION_H#include<stdio.h>#include<stdlib.h>typedefcharBiElemType;typedefstructBiTNode{BiElemTypec;//c就是书籍上的datastru......
  • 从命令行中读入一个文件名,判断该文件是否存在。如果该文件存在,则在原文件相同路径下创
    例如:读入/home/java/photo.jpg则创建一个文件/home/java/copy_photo.jpg新文件内容和原文件内容相同packageio.homework;importjava.io.*;importjava.util.Scanner;publicclassq23{publicstaticvoidmain(String[]args){Scannerscanner=ne......
  • 二叉树前序中序后序遍历实战
    function函数////Createdby93757on2023/3/21.//#ifndefINC_1_TREE_FUNCTION_H#defineINC_1_TREE_FUNCTION_H#include<stdio.h>#include<stdlib.h>typedefcharBiElemType;typedefstructBiTNode{BiElemTypec;//c就是书籍上的datastru......
  • 14.4二叉树层次建树
    创建function函数////Createdby93757on2023/3/21.//#ifndefINC_1_TREE_FUNCTION_H#defineINC_1_TREE_FUNCTION_H#include<stdio.h>#include<stdlib.h>typedefcharBiElemType;typedefstructBiTNode{BiElemTypec;//c就是书籍上的datast......
  • 剑指 Offer 37. 序列化二叉树
    题目链接:剑指Offer37.序列化二叉树取巧做法classCodec{private:TreeNode*root;public://Encodesatreetoasinglestring.stringserialize(TreeNode*root){this->root=root;return"";}//Decodesyourencoded......
  • 判断字符串是不是正则表达式
    :rules="[{required:true,trigger:'blur',validator:this.checkCanonical},]"checkCanonical(rule,value,callback){if(value){letisReg=truetry{isReg=eval(......
  • Xbox Series X 完全关机教程 All In One
    XboxSeriesX完全关机教程AllInOne主机的风扇完全停止工作✅https://www.douyin.com/video/7193633798267915581https://www.biaopan8.com/9985.html(......
  • JZ8 二叉树的下一个结点
    做法一:直接求出中序遍历,并用vector容器存储。/*structTreeLinkNode{intval;structTreeLinkNode*left;structTreeLinkNode*right;structTreeLinkNode*next;TreeLinkNode(intx):val(x),left(NULL),right(NULL),next(NULL){......
  • 链表的回文判断—Java实现
    对于这个题,主要是老是局限于方法内的变量,未想到借助外部变量辅助:具如下,不可用数除法,会溢出异常:即使是取最大的long也会溢出,常规方法不再赘述,具体以代码如下:1packageProblemSolve;23publicclassSolution5{4privateListNodefrontNode;5publicboolean......
  • C#判断字符串是否是有效的XML格式数据
    说明在try-catch语句块中,创建XmlDocument对象,并使用LoadXml方法加载xml字符串。如果没有异常,则说明xml字符串是有效的,返回true,反之为false。代码实现///<summary>///Xml字符串格式验证///</summary>///<paramname="xmlString">Xm......