顺序二叉树

Binary Tree

#include<iostream>
#include<math.h>
using namespace std;

#define MAXSIZE 100

enum ECCHILDSIGN            //节点标记
{
    E_root,                 //树根
    E_ChildLeft,            //左孩子
    E_ChildRight            //右孩子
};

template<typename T>
struct BinaryTreeNode
{
    T data;                 //数据域
    bool isValid;           //该节点是否有效以应对非完全二叉树(只有保存了实际节点数据节点才是有效的)
};   

//二叉树的定义
template<typename T>
class BinaryTree
{
    public:
        BinaryTree()                           //构造函数
        {
            for(int i = 0; i < MAXSIZE; ++i)   //注意这里数组大小为 MAXSIZE  + 1
            {
                SqBiTree[i].isValid = false;   //开始的时候节点无效
            }
        }
        ~BinaryTree(){}                        //析构函数不需要做什么
    
    public:
        //创建一个树节点
        int CreateNode(int parindex, ECCHILDSIGN pointSign, const T& e);
        
        //获取父节点的下标
        int  getParentIdx(int sonindex)
        {
            if(ifValidRangeIdx(sonindex) == false)      //位置不合理
            {
                return -1;
            }
            if(SqBiTree[sonindex].isValid == false)     //不是个合理节点
            {
                return -1;
            }
            return int(sonindex / 2);
        }

        //获取某个节点所在的高度,根据性质:具有n(n > 0)个节点的完全二叉树的高度 log(n + 1)向上取整 或者是log(n)向下取整 + 1
        int getPointLevel(int index)   
        {
            if(ifValidRangeIdx(index) == false)      //位置不合理
            {
                return -1;
            }
            if(SqBiTree[index].isValid == false)     //不是个合理节点
            {
                return -1;
            }

            //采用计算公式: log(n)向下取整 + 1
            int level = int(log(index) / log(2)) +1;//c++中的log(n)函数是以 e 为底
            return level;
        }

        //获取二叉树的深度
        int GetLevel()
        {
            if(SqBiTree[1].isValid == false)   //没根
            {
                return 0;
            }
            int i;
            for(i = MAXSIZE; i >= 1; --i)
            {
                if(SqBiTree[i].isValid == true)
                {
                    break;
                }
            }
            return getPointLevel(i);
        }

        //判断是否是个完全二叉树
        bool ifComplateBT()
        {
            if(SqBiTree[1].isValid == false)   //没根
            {
                return false;
            }
            int i;
            for(i = MAXSIZE; i >= 1; --i)
            {
                if(SqBiTree[i].isValid == true)
                    break;
            }
            for(int k = 1; k <= i; ++k)
            {
                if(SqBiTree[k].isValid == false)
                {
                    return false;
                }
            }
            return true;
        }

        //前序遍历二叉树,其他遍历的方式在二叉树的链式存储中在详细书写
        void preOrder()
        {
            if(SqBiTree[1].isValid == false)   //没根
            {
                return ;
            }
            preOrder(1);            //根节点的数组下标是1, 所以这里把根的下标传递进去
        }

        void preOrder(int index)
        {
            if(ifValidRangeIdx(index) == false)      //位置不合理
            {
                return ;
            }
            if(SqBiTree[index].isValid == false)     //不是个合理节点
            {
                return ;
            }
            //根左右
            cout << (char)SqBiTree[index].data << " ";   //输出节点数据域的值
            preOrder(2 * index);                         //递归方式遍历左子树
            preOrder(2 * index + 1);                     //递归方式遍历右子树
        }
        
    private:
        bool ifValidRangeIdx(int index)         //是否是一个有效的数组下标值
        {
            //位置必须合理
            if(index < 1 || index > MAXSIZE)    //[0]号位置不用
                return false;
            return true;
        }

    private:
        BinaryTreeNode<T> SqBiTree[MAXSIZE + 1];  //存储二叉树节点的数组,下标为0不使用
};

//创建一个树节点
template<typename T>  
int BinaryTree<T>::CreateNode(int parindex, ECCHILDSIGN pointSign, const T& e)
{
    //参数一:父节点所在的数组下标
    //参数二:标记所创建的是树根,左孩子,右孩子。
    //参数三: 插入的数据节点的元素值
    
    if(pointSign != E_root)     //非根节点,则一定是子节点,要求parindex一定是个合理值
    {
        if(ifValidRangeIdx(parindex) == false)      //位置不合理
        {
            return -1;
        }
        if(SqBiTree[parindex].isValid == false)     //不是个合理节点
        {
            return -1;
        }
    }

    int index = -1;
    if( pointSign == E_root )
    {
        index = 1;                  //根节点固定存储在下标为 1 的位置
    }

    else if(pointSign == E_ChildLeft)   //左孩子
    {
        //创建的是左孩子节点,节点 i 的左孩子 节点的下标是 2i
        index = 2 * parindex;
        if(ifValidRangeIdx(index) == false)      //位置不合理
        {
            return -1;
        }
    }
    else
    {
        //创建的是右孩子节点,节点 i 的右孩子 节点的下标是 2i + 1
        index = 2 * parindex + 1;
        if(ifValidRangeIdx(index) == false)      //位置不合理
        {
            return -1;
        }
    }
    SqBiTree[index].data = e;
    SqBiTree[index].isValid = true;      //标记该下标中有有效数据
    return index;
}

int main()
{
    BinaryTree<int> mytree;
    //创建一个二叉树
    int indexRoot = mytree.CreateNode(-1,E_root,'A');   //创建数根节点
    int indexNodeB = mytree.CreateNode(indexRoot, E_ChildLeft,'B'); //创建左子节点
    int indexNodeC = mytree.CreateNode(indexRoot, E_ChildRight, 'C');//创建右子节点

    int indexNodeD = mytree.CreateNode(indexNodeB, E_ChildLeft,'D'); //创建左子节点
    int indexNodeE = mytree.CreateNode(indexNodeC, E_ChildRight, 'E');//创建右子节点

    int iParentIndexE = mytree.getParentIdx(indexNodeE);        //获取某个节点的父节点下标
    cout << "节点E的父节点的下标是: " << iParentIndexE << endl;

    int iLevel = mytree.getPointLevel(indexNodeD);      //获取某个节点所在的高度
    cout << "节点D所在的高度是: " << iLevel << endl;

    iLevel = mytree.getPointLevel(indexNodeE);      //获取某个节点所在的高度
    cout << "节点E所在的高度是: " << iLevel << endl;

    cout << "二叉树的深度是: " << mytree.GetLevel() << endl;
    cout << "二叉树是完全二叉树吗? " << mytree.ifComplateBT() << endl;

    cout << "------------------" << endl;

    cout << "前序遍历序列为: ";
    mytree.preOrder();      //前序遍历
    cout << endl;
    return 0;
}

 

posted @ 2022-07-26 17:54  huahuati  阅读(37)  评论(0)    收藏  举报