二叉树的创建和基本操作(递归和非递归)

二叉树的定义在这里不做陈述,我们直接来看看如何实现一个二叉树的创建(c++)

首先定义结点,这里我们呢用结构体来创建

template<typename T>
struct BinaryTreeNode   //创建孩子二叉树的结点
{
    BinaryTreeNode(const T& data = T())
    :_data(data)
    , _pLeft(NULL)
    , _pRight(NULL)
    {}

    T _data;
    BinaryTreeNode* _pLeft;
    BinaryTreeNode* _pRight;
};

定义好结点之后我们就可以来想办法创建一个二叉树类,其中包含二叉树的创建和基本操作

template<typename T>
class BinaryTree
{
    typedef BinaryTreeNode<T> Node;
public:
    BinaryTree()
        : _pRoot()
    {}

    /***********用函数封装来做************/
    BinaryTree(const T* array, size_t size, const T& invalid)  //构造函数构造二叉树
    {
        size_t index = 0;
        _pRoot = CreatTree(array, size, index, invalid);
    }

    BinaryTree(const BinaryTree<T>& b)  //拷贝构造一个相同的二叉树
    {
        _pRoot = Copy(b._pRoot);
    }

    BinaryTree& operator=(BinaryTree<T>& b)  //重载=
    {
        if (this != &b)  //防止自己给自己赋值
        {
            BinaryTree<T> tem(b);
            std::swap(_pRoot, tem._pRoot);
        }
        return *this;
    }

    ~BinaryTree()  //析构函数释放树
    {
        Destory(_pRoot);
    }

    size_t _Leaf()  //求叶子结点个数
    {
        return Leaf(_pRoot);
    }

    size_t _Size()  //求结点个数
    {
        return Size(_pRoot);
    }

    size_t _Depth()  //求树的深度
    {
        return Depth(_pRoot);
    }

    void _PreOder()  //先序遍历
    {
        PreOder(_pRoot);
        cout << endl;
    }

    void _InOder()  //中序遍历
    {
        InOder(_pRoot);
        cout << endl;
    }

    void _BackOder()  //后序遍历
    {
        BackOder(_pRoot);
        cout << endl;
    }
protected:
    Node* _pRoot;
}

创建好这个二叉树类之后我们来将其中的功能进行相应的实现(这里我将所有的函数实现都已private的形式写在了类内部)

··········创建二叉树
/*先序递归创建二叉树*/
        Node* CreatTree(const T* array, size_t size, size_t& index, const T& invalid)
    {
        assert(array);

        Node* pRoot = NULL;
        if (index < size&&array[index] != invalid)
        {
            pRoot = new Node(array[index]);
            pRoot->_pLeft = CreatTree(array, size, ++index, invalid);
            pRoot->_pRight = CreatTree(array, size, ++index, invalid);
        }

        return pRoot;
    }

/*非递归创建二叉树*/
    Node *CreatTree(const T* a, size_t size, size_t index, const T& invalid)
    {
        stack<Node*> s;
        Node* pRoot = new Node(a[index++]);
        int flag = 1;         //flag  =1创建左孩子,=2创建右孩子,=3出栈  
        s.push(pRoot);
        Node *pPre = NULL;
        Node *pCur = NULL;

        while (index<size)
        {
            if (flag == 1)      //创建左孩子  
            {
                if (a[index] == invalid)     //如果左孩子为空,则flag=2创建右孩子  
                {
                    flag = 2;
                }
                else
                {
                    pCur = new Node(a[index]);
                    pPre = s.top();
                    pPre->_pLeft = pCur;          //链接到左指针上  
                    s.push(pCur);               //将新节点压入栈中  
                }
            }
            else if (flag == 2)              //flag=2,创建右孩子  
            {
                if (a[index] == invalid)        //如果右孩子为空,则flag=3准备出栈  
                {
                    flag = 3;
                }
                else
                {
                    pCur = new Node(a[index]);
                    pPre = s.top();
                    pPre->_pRight = pCur;          //链接到左指针上  
                    s.push(pCur);               //将新节点压入栈中  
                    flag = 1;                  //再创建新结点的左孩子  
                }
            }
            else
            {
                if (!s.empty())
                {
                    pPre = s.top();
                    s.pop();
                }
                //如果已经出栈的元素是当前栈顶的右孩子,则表示这个结点的左右子树已经创建完毕,则一直出栈  
                while (!s.empty() && s.top()->_pRight == pPre)
                {
                    pPre = s.top();
                    s.pop();
                }

                flag = 2;
                index--;
            }
            index++;
        }
        return pRoot;
    }



··········先序遍历
/*递归先序遍历*/
    void PreOder(Node* pRoot)
    {
        Node* pCur = pRoot;

        if (pCur)
        {
            cout << pCur->_data << " ";
            PreOder(pCur->_pLeft);
            PreOder(pCur->_pRight);
        }
    }

/*非递归先序遍历*/
    void PreOder(Node* _pRoot)
    {
        assert(_pRoot);

        Node *pRoot = _pRoot;
        stack<Node*> s;
        s.push(pRoot);
        int flag = 1;
        Node *pCur = NULL;

        while (!s.empty())
        {
            pCur = s.top();
            if (flag == 1)                  //遍历左子树  
            {
                if (pCur->_pLeft == NULL)    //如果左子树为空,则flag=2  
                {
                    flag = 2;
                }
                else
                {
                    cout << pCur->_Data << " ";    //先序输出,先输出根结点  
                    s.push(pCur->_pLeft);
                }
            }
            else if (flag == 2)
            {
                if (pCur->_pRight == NULL)
                {
                    flag = 3;
                }
                else
                {
                    s.push(pCur->_pRight);
                    flag = 1;
                }
            }
            else
            {
                Node *pPre = NULL;
                if (!s.empty())
                {
                    pPre = s.top();
                    s.pop();
                }
                pCur = pPre;
                while (!s.empty() && s.top()->_pRight == pPre)  //将输出过的结点出栈  
                {
                    pPre = s.top();
                    s.pop();
                }
                if (!s.empty())         //输出右子树的叶子节点  
                {
                    cout << pCur->_Data << " ";
                }
                flag = 2;
            }
        }
        cout << endl;
    }



·········中序遍历
/*递归中序遍历*/
    void InOder(Node* pRoot)
    {
        Node* pCur = pRoot;

        if (pCur)
        {
            InOder(pCur->_pLeft);
            cout << pCur->_data << " ";
            InOder(pCur->_pRight);
        }
    }

/*非递归中序遍历*/
    void InOder(Node* _pRoot)
    {
        assert(_pRoot);

        Node *pRoot = _pRoot;
        stack<Node*> s;
        s.push(pRoot);
        int flag = 1;

        while (!s.empty())
        {
            Node *pCur = s.top();
            if (flag == 1)                  //先遍历左子树  
            {
                if (pCur->_pLeft == NULL)
                {
                    flag = 2;
                }
                else
                {
                    s.push(pCur->_pLeft);
                }
            }
            else if (flag == 2)        //遍历右子树  
            {
                if (pCur->_pRight == NULL)
                {
                    flag = 3;
                }
                else
                {
                    cout << pCur->_Data << " ";        //输出右子树的跟结点  
                    s.push(pCur->_pRight);
                    flag = 1;
                }
            }
            else
            {
                Node* pPre = NULL;
                if (!s.empty())
                {
                    pPre = s.top();
                    s.pop();
                }
                cout << pPre->_Data << " ";          //输出左子树结点和左子树的根结点  

                while (!s.empty() && s.top()->_pRight == pPre)
                {
                    pPre = s.top();
                    s.pop();
                }
                flag = 2;
            }
        }
        cout << endl;
    }



········后序遍历
/*递归后序遍历*/
    void BackOder(Node* pRoot)
    {
        Node* pCur = pRoot;

        if (pCur)
        {
            BackOder(pCur->_pLeft);
            BackOder(pCur->_pRight);
            cout << pCur->_data << " ";
        }
    }

/*非递归后序遍历*/
    void BackOder(Node* _pRoot)
    {
        assert(_pRoot);

        Node *pRoot = _pRoot;
        stack<Node*> s;
        int flag = 1;       //=1遍历左子树,=2 遍历右子树,=3 输出结点  
        s.push(pRoot);       //根节点入栈  
        Node *pCur = NULL;

        while (!s.empty())
        {
            pCur = s.top();
            if (flag == 1)              //遍历左子树  
            {
                if (pCur->_pLeft == NULL)   //如果左子树为空,则flag=2,准备遍历右子树  
                {
                    flag = 2;
                }
                else
                {
                    s.push(pCur->_pLeft);
                }
            }
            else if (flag == 2)             //遍历右子树  
            {
                if (pCur->_pRight == NULL)       //右子树为空,准备输出结点  
                {
                    flag = 3;
                }
                else
                {
                    s.push(pCur->_pRight);
                    flag = 1;                //遍历当前结点的左子树  
                }
            }
            else
            {
                Node *pPre = NULL;
                if (!s.empty())
                {
                    pPre = s.top();    //保存当前栈顶元素  
                    s.pop();          //抛出栈顶元素  
                }
                cout << pPre->_Data << " ";    //输出结点的信息  

                //如果当前栈顶元素的右子树是pPre,则抛出pPre之后按照后序也要抛出栈顶元素  
                while (!s.empty() && s.top()->_pRight == pPre)
                {
                    pPre = s.top();    //保存当前栈顶元素  
                    s.pop();          //抛出栈顶元素  
                    cout << pPre->_Data << " ";    //输出结点的信息  
                }
                flag = 2;
            }
        }
        cout << endl;
    }



········求叶子结点个数
/*递归*/
        size_t Leaf(Node* pRoot)
    {
        Node* pCur = pRoot;

        if (NULL == pCur)
            return 0;

        if (pCur->_pLeft == NULL&&pCur->_pRight == NULL)      //如果左右子树都为空,则返回1  
            return 1;

        return Leaf(pCur->_pLeft) + Leaf(pCur->_pRight);
    }

/*非递归*/ 
    size_t Leaf(Node* pRoot)
    {
        size_t index = 0;
        Node* pCur = pRoot;
        stack<Node*> s;

        while (pCur || !s.empty())
        {
            while (pCur)
            {
                //如果左右子树都为空,则为叶子结点  
                if (pCur->_pLeft == NULL&&pCur->_pRight == NULL)
                    index++;
                s.push(pCur);
                pCur = pCur->_pLeft;
            }
            Node* pPre = s.top();
            s.pop();
            pCur = pPre ->_pRight;
        }
        return index;
    }



·········求结点个数
/*递归*/
    size_t Size(Node* pRoot)
    {
        if (pRoot == NULL)
            return 0;

        return 1 + Size(pRoot->_pLeft) + Size(pRoot->_pRight);
    }

/*非递归*/
       size_t Size(Node* pRoot)
    {
        size_t index = 0;
        Node* pCur = pRoot;
        stack<Node*> s;

        while (pCur || !s.empty())
        {
            while (pCur)
            {
                index++;        //遍历一个结点就让count++  
                s.push(pCur);
                pCur = pCur->_pLeft;
            }
            Node * top = s.top();
            s.pop();
            pCur = top->_pRight;
        }
        return index;
    }



········树的深度
/*递归*/
        size_t Depth(Node* pRoot)
    {
        Node* pCur = pRoot;

        if (NULL == pCur)
            return 0;

        return 1 + (Depth(pCur->_pLeft) > Depth(pCur->_pRight)
            ? Depth(pCur->_pLeft) : Depth(pCur->_pRight));
    }

/*非递归*/
        size_t Depth(Node* pRoot)
    {
        if (pRoot == NULL)
            return 0;

        queue<Node*> q;
        size_t deep = 0;
        size_t  NodeNum = 1;      //统计有多少数据入过队  
        size_t  LeveLast = 1;      //标记正在访问的这层的最后一个数据的序号  
        size_t  VisitNum = 0;       //统计已经出队的数据的个数  
        q.push(pRoot);

        while (!q.empty())
        {
            Node* pCur = q.front();
            q.pop();
            VisitNum++;
            if (NULL != pCur->_pLeft)
            {
                q.push(pCur->_pLeft);
                NodeNum++;
            }
            if (NULL != pCur->_pRight)
            {
                q.push(pCur->_pRight);
                NodeNum++;
            }
            //如果以出队的个数等于这一层的最后一个数据的序号  
            if (LeveLast == VisitNum)
            {
                deep++;                //访问完一层就让深度加一  
                LeveLast = NodeNum;    //更新到下一层的最后一个数据的位置  
            }
        }
        return deep;
    }

创建好之后让我么来测试一下,首先测试递归版本的二叉树
测试代码如下

void FunTest()
{
    int array[] = { 1, 2, 3, '#', 4, '#', '#', 5, 6, '#', '#', 7 };
    BinaryTree<int> t(array, sizeof(array) / sizeof(array[0]), '#');

    cout << t._Leaf() << endl;
    cout << t._Size() << endl;
    cout << t._Depth() << endl;
    t._PreOder();
    t._InOder();
    t._BackOder();
}

int main()
{
    FunTest();

    return 0;
}

输出结果为
这里写图片描述

接下来是非递归版本的二叉树
测试代码如下

void FunTest()
{
    int arr[] = { 1, 2, 3, '#', '#', 4, '#', '#', 5, 6 };
    BinaryTree<int> t(arr, sizeof(arr) / sizeof(arr[0]), '#');
    t._PrevOder();
    t._InOder();
    t._BackOder();
    cout << t._Leaf() << endl;
    cout << t._Size() << endl;
    cout << t._Depth() << endl;

}

int main()
{
    FunTest();
    system("pause");
    return 0;
}

输出结果为
这里写图片描述

以上就是二叉树的创建及基本操作

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值