【数据结构·树】二叉树:完全二叉树的判断 (附:新定义一个结构体类型,用队列存储;模板实例化)C++

附:

为了用队列既存储树的结点,又存储当前结点左右孩子对应的编号(若是完全二叉树,该结点(i)的左孩子为2i,右孩子为2i+1)

层次遍历结束后,判断结点总数sum是否==队列中最后一个元素的编号。

定义结构体:

struct elem{

  BinaryTreeNode<ElemType> *node;

  int num; 

};

定义队列:

queue<elem<string>> q;  //!别忘了elem也要实例化!!


 

问题描述

目的:使用C++模板设计并逐步完善二叉树的抽象数据类型(ADT)。

内容:(1)请参照链表的ADT模板,设计二叉树并逐步完善的抽象数据类型。(由于该环境目前仅支持单文件的编译,故将所有内容都集中在一个源文件内。在实际的设计中,推荐将抽象类及对应的派生类分别放在单独的头文件中。参考教材、课件,以及网盘中的链表ADT原型文件,自行设计二叉树的ADT。)

注意:二叉树ADT的基本操作的算法设计很多要用到递归的程序设计方法。

(2)基本操作16:在二叉树的二叉链表存储形式建立的基础上,设计并完成判断二叉树是否为完全二叉树的算法。完成后将其加入到二叉树的ADT基本操作集中。

提示:如果一棵二叉树是完全二叉树,那么按照二叉树的性质5可知,按层编号的最后一个结点的编号等于树上的结点总数。因此,可以层次遍历这棵树。在层次遍历时,对树的每一个结点标记一个数值。标记方法如下:根结点为1。对于每个标记值为n的结点,它的两个孩子结点的标号值分别为2n和2n+1。在遍历时,顺便统计树上的结点个数。当结点数等于最后一个结点的编号时,这棵树是完全二叉树,反之为非完全二叉树。与层次遍历(基本操作5)不同的是,在判断完全二叉树时,队列中不仅要保存指向结点的指针,还需要保存结点的编号。为此在二叉树的数据成员里添加了一个结构体类型作为队列中的元素类型。它的定义如下:

struct elem{

  BinaryTreeNode<ElemType> *node;

  int num; 

};

参考函数原型:

template<class ElemType>  判断是否是完全二叉树

bool BinaryTree<ElemType>::isCompleteTree() const;

输入说明

第一行:表示无孩子或指针为空的特殊分隔符

第二行:二叉树的先序序列(结点元素之间以空格分隔)

输出说明

第一行:完全二叉树:true

     非完全二叉树:false

输入范例

#
A B D # # E # # C F # # # #

输出范例

true

AC代码

#include<iostream>
#include <sstream>
#include<string>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<stack>
#include<vector>
#include <climits>
#include<queue>
#define MAX_SIZE 100
using namespace std;
bool sign;
//结点
template<class ElemType>
struct BinaryTreeNode
{
       ElemType data;
       BinaryTreeNode<ElemType> *LChild, *RChild,*parent;
       BinaryTreeNode() : LChild(NULL), RChild(NULL),parent(NULL){}
       BinaryTreeNode(const ElemType &item, BinaryTreeNode<ElemType> *p = NULL,BinaryTreeNode<ElemType> *Lptr = NULL, BinaryTreeNode<ElemType> *Rptr = NULL)
       {
           parent=p;
           LChild = Lptr;
           RChild = Rptr;
           data = item;
       }
};
//二叉树
template<class ElemType>
class BinaryTree
{
   private:
      BinaryTreeNode<ElemType> *root;
      int sum;//记录结点数
   public:
      BinaryTree():root(NULL){sum=0;}
      BinaryTree(const ElemType &item){root = new BinaryTreeNode<ElemType>(item);sum=0;}
      ~BinaryTree()
      {
          Destory(root);
      }
      void Destory(BinaryTreeNode<ElemType> * root)
      {
        if (root==NULL)
        {
            return;
        }
        Destory(root->LChild);
        Destory(root->RChild);
        delete root;
      }
      void makeBinaryTree( const ElemType &item, BinaryTree &left, BinaryTree &right);
      int BinaryTreeSize( BinaryTreeNode<ElemType> *T ) const;
      bool BinaryTreeisEmpty() const{return root == NULL;}
      ElemType GetRootData() const{ return root->data;}
      void SetRoot(BinaryTreeNode<ElemType> * p){ root = p;}
      BinaryTreeNode<ElemType> * GetRoot() const{ return root;}
      bool PreOrderTraverse( BinaryTreeNode<ElemType> *T );  //前序遍历(递归)
      bool InOrderTraverse( BinaryTreeNode<ElemType> *T );  //中序遍历(递归)
      bool PostOrderTraverse( BinaryTreeNode<ElemType> *T );  //后序遍历(递归)
      BinaryTreeNode<ElemType>* CreateBinaryTree(vector<ElemType> &x, ElemType &empty, int &n);
      bool isCompleteTree() const;
};
//负责记录结点
template<class ElemType>
struct elem
      {
         BinaryTreeNode<ElemType> *node;
         int num;
      };
//定义队列
queue<elem<string>> q;
//层次遍历判断是否为完全二叉树
template<class ElemType>
bool BinaryTree<ElemType>::isCompleteTree() const
{

    if(root)
    {
        int k=1;
        ElemType e;
        elem<ElemType> val;
        val.node=root;
        val.num=k;
        q.push(val);
        while(!q.empty())
        {
            auto t=q.front();
            k=t.num;
            q.pop();
            if(t.node->LChild!=NULL)
            {
                auto p=t.node->LChild;
                elem<ElemType> val;
                val.node=p;
                val.num=2*k;
                q.push(val);
            }
            if(t.node->RChild!=NULL)
            {
                auto p=t.node->RChild;
                elem<ElemType> val;
                val.node=p;
                val.num=2*k+1;
                q.push(val);
            }
        }
        if(k==sum)return true;
        else return false;
    }
    return false;
}
//创建树
template<class ElemType>
BinaryTreeNode<ElemType>* BinaryTree<ElemType>::CreateBinaryTree(vector<ElemType> &x, ElemType &empty, int &n)
{
        ElemType ch = x[n];//string
        n++;
        if (ch == empty)
        {
            return NULL;
        }
        else
        {
            BinaryTreeNode<ElemType> *Node = new BinaryTreeNode<ElemType>;
            Node->data = ch;sum++;
            Node->LChild = CreateBinaryTree(x, empty, n);
            Node->RChild = CreateBinaryTree(x, empty, n);
            return Node;
        }
}
//准备创建树
template<class ElemType>
void CreateTree(BinaryTree<ElemType> &T, ElemType &str, ElemType &empty)
{
    ElemType tmp;
    vector<ElemType> t;
    stringstream input_T(str);
    while(input_T >> tmp)
    {
         t.push_back(tmp);
    }
    BinaryTreeNode<ElemType> *root;
    int num = 0;
    root = T.CreateBinaryTree(t, empty, num);
    T.SetRoot(root);

}

int main()
{
    BinaryTree<string> T;
    string str;
    string empty;
    getline(cin,empty);
    getline(cin,str);
    CreateTree(T,str,empty);
    if(T.isCompleteTree())cout<<"true";
    else cout<<"false";
    return 0;
}
 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值