判断一棵树是否是完全二叉树

1.【基础题】–判断一棵树是否是完全二叉树。提示:层序遍历变型题。

(1)基础知识
【二叉树】:二叉树是一棵特殊的树,二叉树每个节点最多有两个孩子结点,分别称为左孩子和右孩子。

【满二叉树】:高度为N的满二叉树有2^N- 1个节点的二叉树。

【完全二叉树】: 若设二叉树的深度为h,除第h 层外,其它各层(1~h-1) 的结点数都达到最大个数,第h 层所有的结点都连续集中在最左边,这就是完全二叉树
【满二叉树是完全二叉树的特例】
这里写图片描述
(2)判断一棵树是否是完全二叉树的思路
1>如果树为空,则直接返回错
2>如果树不为空:层序遍历二叉树
2.1>如果一个结点左右孩子都不为空,则pop该节点,将其左右孩子入队列;
2.1>如果遇到一个结点,左孩子为空,右孩子不为空,则该树一定不是完全二叉树;
2.2>如果遇到一个结点,左孩子不为空,右孩子为空;或者左右孩子都为空;则该节点之后的队列中的结点都为叶子节点;该树才是完全二叉树,否则就不是完全二叉树;

(3)代码实现

#include<iostream>
using namespace std;
#include<queue>
template<class T>
struct TreeNode
{
     T data;
     TreeNode<T>*  left;
     TreeNode<T>*  right;
     TreeNode(const T& x)
         :data(x)
         ,left(NULL)
         ,right(NULL)
     {}
};


----------
template<class T>
bool  IsComplete(TreeNode<T>* root)
{
    //1.树为空,返回错误
   if (root==NULL)
   {
       return false;
   }
   //2.树不为空
   queue<TreeNode<T>*>  q;
   q.push(root);
   while (!q.empty())
   {
       TreeNode<T>* top=q.front();
       //2.1如果该节点两个孩子都有,则直接pop
       if (top->left&&top->right)
       {
           q.pop();
           q.push(top->left);
           q.push(top->right);
       }
       //2.2如果该节点左孩子为空,右孩子不为空,则一定不是完全二叉树
       if (top->left==NULL&&top->right)
       {
           return false;
       }
       //2.3如果该节点左孩子不为空,右孩子为空或者该节点为叶子节点,则该节点之后的所有结点都是叶子节点
       if ((top->left&&top->right==NULL)||(top->left==NULL&&top->right==NULL))
       {
           q.pop();
           //则该节点之后的所有结点都是叶子节点
           while (!q.empty())
           {
               top=q.front();
               if (top->left==NULL&&top->right==NULL)
               {
                   q.pop();
               }
               else
               {
                   return false;
               }
           }
           return true;
       }
   }
   return true;  
}
----------


//满二叉树
void test1()
{
    //       1
    //   2       3
    // 4    5  6   7
     TreeNode<int>* node1=new TreeNode<int>(1); 
     TreeNode<int>* node2=new TreeNode<int>(2); 
     TreeNode<int>* node3=new TreeNode<int>(3); 
     TreeNode<int>* node4=new TreeNode<int>(4); 
     TreeNode<int>* node5=new TreeNode<int>(5); 
     TreeNode<int>* node6=new TreeNode<int>(6); 
     TreeNode<int>* node7=new TreeNode<int>(7); 
     node1->left=node2;
     node1->right=node3;
     node2->left=node4;
     node2->right=node5;
     node3->left=node6;
     node3->right=node7;
     cout<<IsComplete<int>(node1)<<endl;
}

//二叉树为空
void test2()
{
    cout<<IsComplete<int>(NULL)<<endl;
}
//3.二叉树不为空,也不是满二叉树,遇到一个结点左孩子为空,右孩子不为空
void test3()
{
    //       1
    //   2       3
    // 4    5      7
    TreeNode<int>* node1=new TreeNode<int>(1); 
    TreeNode<int>* node2=new TreeNode<int>(2); 
    TreeNode<int>* node3=new TreeNode<int>(3); 
    TreeNode<int>* node4=new TreeNode<int>(4); 
    TreeNode<int>* node5=new TreeNode<int>(5); 
    TreeNode<int>* node7=new TreeNode<int>(7); 
    node1->left=node2;
    node1->right=node3;
    node2->left=node4;
    node2->right=node5;
    node3->right=node7;
    cout<<IsComplete<int>(node1)<<endl;
}

//4.二叉树不为空,也不是满二叉树,遇到叶子节点,则该叶子节点之后的所有结点都为叶子节点
void test4()
{
    //        1
    //    2       3
    // 4    5      
    TreeNode<int>* node1=new TreeNode<int>(1); 
    TreeNode<int>* node2=new TreeNode<int>(2); 
    TreeNode<int>* node3=new TreeNode<int>(3); 
    TreeNode<int>* node4=new TreeNode<int>(4); 
    TreeNode<int>* node5=new TreeNode<int>(5); 
    node1->left=node2;
    node1->right=node3;
    node2->left=node4;
    node2->right=node5;
    cout<<IsComplete<int>(node1)<<endl;
}
//4.二叉树不为空,也不是满二叉树,遇到左孩子不为空,右孩子为空的结点,则该节点之后的所有结点都为叶子节点
void test5()
{
    //        1
    //    2       3
    // 4    5   6 
    TreeNode<int>* node1=new TreeNode<int>(1); 
    TreeNode<int>* node2=new TreeNode<int>(2); 
    TreeNode<int>* node3=new TreeNode<int>(3); 
    TreeNode<int>* node4=new TreeNode<int>(4); 
    TreeNode<int>* node5=new TreeNode<int>(5); 
    TreeNode<int>* node6=new TreeNode<int>(6); 
    node1->left=node2;
    node1->right=node3;
    node2->left=node4;
    node2->right=node5;
    node3->left=node6;
    cout<<IsComplete<int>(node1)<<endl;
}
int main()
{
    test1();
    /*test2();*/
    /*test3();*/
    /*test4();*/
    /*test5();*/
    return 0;
}
评论 8 您还未登录,请先 登录 后发表或查看评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页

打赏作者

gogogo_sky

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值