关于二叉树

//BinNode.h
#ifndef BINNODE_H
#define BINNODE_H

#include <queue>
#include <stack>
#include <vector>

namespace Shawn
{
    template <typename _T>
    class BinNode                                                                      //二叉树节点模板类
    {
        template<typename _T> friend class BinTree;
        template<typename _T, typename _VST>
        friend void travPre(typename BinNode<_T>::_BinNodePtr _x, _VST& _visit);        //递归前序遍历
        template<typename _T, typename _VST>
        friend void travIn(typename BinNode<_T>::_BinNodePtr _x, _VST& _visit);         //递归中序遍历
        template<typename _T, typename _VST>
        friend void travPost(typename BinNode<_T>::_BinNodePtr _x, _VST& _visit);       //递归后序遍历
        template<typename _T>
        friend typename BinNode<_T>::_BinNodePtr reconstruction_pre_in(const size_t _n,  //基于前序、中序遍历的重构
            const std::vector<_T>& _pre, const std::vector<_T>& _in);
        template<typename _T>
        friend typename BinNode<_T>::_BinNodePtr reconstruction_post_in(const size_t _n, //基于后序、中序遍历的重构
            const std::vector<_T>& _post, const std::vector<_T>& _in);
    protected:
        typedef BinNode<_T>* _BinNodePtr;                      //指向节点的指针
        _T _data;                                              //数值
        _BinNodePtr _parent, _lc, _rc;                         //父节点及左、右孩子
        size_t _height;                                        //高度

    public:
        //构造函数:
        BinNode() : _parent(nullptr), _lc(nullptr), _rc(nullptr), _height(0) { }
        BinNode(_T _e, _BinNodePtr _p = nullptr, _BinNodePtr _lc = nullptr, _BinNodePtr _rc = nullptr,
            size_t _h = 0) : _data(_e), _parent(_p), _lc(_lc), _rc(_rc), _height(_h) { }
    public:
        //操作接口:
        size_t size();                      //统计当前节点后代总数,亦即以其为根的子树的规模
        size_t stature()                    //返回当前节点高度,与“空树高度为-1”的约定相统一
        {
            return this ? this->_height : -1;
        }
        _BinNodePtr insertAsLC(_T const&);  //作为当前节点的左孩子插入新节点
        _BinNodePtr insertAsRC(_T const&);  //作为当前节点的右孩子插入新节点
        _BinNodePtr succ();                 //取当前节点(中序遍历意义下的)直接后继

        //遍历接口:
        template<typename _VST> void travLevel(_VST&);   //子树层次遍历
        template<typename _VST> void travPre(_VST&);     //子树先序遍历
        template<typename _VST> void travIn(_VST&);      //子树中序遍历
        template<typename _VST> void travPost(_VST&);    //子树后序遍历


        //遍历辅助函数:

        //先序遍历辅助函数
        template < typename _VST>
        static void _travPre_aux(_BinNodePtr _x, _VST& _visit, std::stack<_BinNodePtr>& _S)
        {
            while (_x)//从当前节点出发,沿左分支不断深入,
                      //直至没有左分支的节点;沿途节点遇到后立即访问
            {
                _visit(_x->_data);               //访问当前节点
                if (_x->_rc) _S.push(_x->_rc);   //右孩子入栈暂存
                _x = _x->_lc;                    //沿左分支深入一层
            }
        }

        //中序遍历辅助函数
        static void _travIn_aux(_BinNodePtr _x, std::stack<_BinNodePtr>& _S)
        {
            while (_x) { _S.push(_x); _x = _x->_lc; } //当前节点入栈后随即向左侧分支深入,
                                                      //迭代直到无左孩子
        }

        //后序遍历辅助函数
        static void _travPost_aux(std::stack<_BinNodePtr>& _S) //在以S栈顶节点为根的子树中,
                                                               //找到最高左侧可见叶节点
        {  
            //沿途所遇节点依次入栈
            while (_BinNodePtr _x = _S.top()) //自顶而下,反复检查当前节点(即栈顶)
            {
                if (_x->_lc)//尽可能向左
                {
                    if (_x->_rc) _S.push(_x->_rc);   //同时有左右孩子,右孩子优先入栈
                    _S.push(_x->_lc);                //然后才转至左孩子
                }
                else       //实不得已才向右
                {
                    _S.push(_x->_rc);
                }
            }
            _S.pop();                               //弹出栈顶空节点
        }

        //比较器:
        bool operator== (BinNode const& _bn) { return _data == _bn._data; }
        bool operator!= (BinNode const& _bn) { return !(*this == _bn); }
        bool operator< (BinNode const& _bn) { return _data < _bn._data; }
        bool operator> (BinNode const& _bn) { return _bn < *this; }
        bool operator<= (BinNode const& _bn) { return !(_bn < *this); }
        bool operator>= (BinNode const& _bn) { return !(*this < _bn); }
    };

    template<typename _T>
    size_t BinNode<_T>::size()
    {
        size_t _tmp = 1;                     //计入自身
        if (_lc) size_t _tmp += _lc->size(); //递归计算左子树
        if (_rc) size_t _tmp += _rc->size(); //递归计算右子树
        return _tmp;
    }

    template<typename _T>
    typename BinNode<_T>::_BinNodePtr BinNode<_T>::insertAsLC(_T const& _e)
    {
        return _lc = new BinNode(_e, this);           //将e作为当前节点的左孩子插入二叉树
    }

    template<typename _T>
    typename BinNode<_T>::_BinNodePtr BinNode<_T>::insertAsRC(_T const& _e)
    {
        return _rc = new BinNode(_e, this);            //将e作为当前节点的右孩子插入二叉树
    }

    template <typename _T>
    typename BinNode<_T>::_BinNodePtr BinNode<_T>::succ()  //定位节点v的直接后继
    {
        _BinNodePtr _tmp = this;                     //记录后继的临时变量
        if (_rc)                                     //若有右孩子,则直接后继必在右子树中
        {
            _tmp = _rc;
            while (_tmp->_lc) _tmp = _tmp->_lc;       //右子树中最靠左(最小)的节点
        }
        else                                         //否则,直接后继应是“将当前节点包含于其左子树中的最低祖先”,
                                                     //具体地就是:
        {
            while (_tmp->_parent/*非根节点*/ && _tmp->_parent->_rc == _tmp/*是某个节点的右孩子*/)
                _tmp = _tmp->_parent;                //逆向地沿右向分支,不断朝左上方移动
            _tmp = _tmp->_parent;                    //最后再朝右上方移动一步,即抵达直接后继(如果存在)
        }
        return _tmp;
    }

    template<typename _T>
    template<typename _VST>
    void BinNode<_T>::travLevel(_VST& _visit)    //以调用节点为根节点的层次遍历
    {
        std::queue<_BinNodePtr> Q;               //辅助队列
        Q.push(this);                            //根节点入队
        while (!Q.empty())
        {
            _BinNodePtr _x = Q.front(); Q.pop(); _visit(_x->_data); //取出队首节点并访问之
            if (_x->_lc) Q.push(_x->_lc);          //左孩子入队
            if (_x->_rc) Q.push(_x->_rc);          //右孩子入队
        }
    }

    template<typename _T>
    template<typename _VST>
    void BinNode<_T>::travPre(_VST& _visit)   //从调用节点出发的先序遍历
    {
        stack<_BinNodePtr> _S;                //辅助栈
        _BinNodePtr _tmp = this;
        while (true)
        {

            _travPre_aux(_tmp, _visit, _S);   //从当前节点出发,逐批访问
            if (_S.empty()) break;            //直到栈空
            _tmp = _S.top();                  //弹出下一批的起点
            _S.pop();
        }
    }

    template<typename _T>
    template<typename _VST>
    void BinNode<_T>::travIn(_VST& _visit)                  //从调用节点出发的中序遍历
    {
        std::stack<_BinNodePtr> _S;                         //辅助栈
        _BinNodePtr _tmp = this;
        while (true)
        {
            _travIn_aux(_tmp, _S);                           //从当前节点出发,逐批入栈
            if (_S.empty()) break;                           //直至所有节点处理完毕
            _tmp = _S.top(); _S.pop(); _visit(_tmp->_data);  //弹出栈顶节点并访问之
            _tmp = _tmp->_rc;                                //转向右子树
        }
    }

    template <typename _T>
    template<typename _VST>
    void BinNode<_T>::travPost(_VST& _visit)      //从调用节点出发的后序遍历
    {
        std::stack<_BinNodePtr> _S;               //辅助栈
        if (this) _S.push(this);                  //根节点入栈
        _BinNodePtr _tmp = this;
        while (!_S.empty())
        {
            if (_S.top() != _tmp->_parent)         //若栈顶非当前节点之父(则必为其右兄),此时需
                _travPost_aux(_S);                 //在以其右兄为根之子树中,找到最高左侧可见叶节点
            _tmp = _S.top(); _S.pop(); _visit(_tmp->_data);  //弹出栈顶(即前一节点之后继),并访问之
        }
    }

    //递归版本遍历接口:
    template<typename _T, typename _VST>
    inline
        void travPre(typename BinNode<_T>::_BinNodePtr _x, _VST & _visit) //先序遍历
    {
        if (!_x) return;
        _visit(_x->_data);
        travPre<_T>(_x->_lc, _visit);
        travPre<_T>(_x->_rc, _visit);
    }
    template<typename _T, typename _VST>
    inline
        void travIn(typename BinNode<_T>::_BinNodePtr _x, _VST & _visit) //中序遍历
    {
        if (!_x) return;
        travIn<_T>(_x->_lc, _visit);
        _visit(_x->_data);
        travIn<_T>(_x->_rc, _visit);
    }
    template<typename _T, typename _VST>
    inline
        void travPost(typename BinNode<_T>::_BinNodePtr _x, _VST & _visit) //后序遍历
    {
        if (!_x) return;
        travPost<_T>(_x->_lc, _visit);
        travPost<_T>(_x->_rc, _visit);
        _visit(_x->_data);
    }

    template<typename _T>
    typename BinNode<_T>::_BinNodePtr reconstruction_pre_in(const size_t _n, //基于前序、中序遍历的重构
        const std::vector<_T>& _pre, const std::vector<_T>& _in)
    {
        if (_pre.size() != _in.size() || _n <= 0)               //递归基
        {
            return nullptr;
        }

        typename BinNode<_T>::_BinNodePtr _root = new BinNode<_T>(_pre[0]); //根节点

        size_t _index = 0;
        for (; _index != _n; ++_index)     //在中序序列中找根节点
        {
            if (_pre[0] == _in[_index])
            {
                break;
            }
        }
        if (_index < 0 || _index >= _n)
        {
            exit(1);
        }

        vector<_T> _left_tree_pre, _left_tree_in, _right_tree_pre, _right_tree_in; //用以保存左、右子树的前序、中序序列

        for (size_t _i = 0; _i < _index; _i++)             //从原序列中提取左、右子树的前序、中序序列
        {
            _left_tree_pre.push_back(_pre[_i + 1]);
            _left_tree_in.push_back(_in[_i]);
        }
        for (size_t _i = _index + 1; _i < _in.size(); _i++)
        {
            _right_tree_pre.push_back(_pre[_i]);
            _right_tree_in.push_back(_in[_i]);
        }
        //递归调用重构函数
        _root->_lc = reconstruction_pre_in(_left_tree_pre.size(), _left_tree_pre, _left_tree_in);
        _root->_rc = reconstruction_pre_in(_right_tree_pre.size(), _right_tree_pre, _right_tree_in);
        return _root;
    }

    template<typename _T>  ////基于后序、中序遍历的重构,思想同上
    typename BinNode<_T>::_BinNodePtr reconstruction_post_in(const size_t _n, const std::vector<_T>& _post, const std::vector<_T>& _in)
    {
        if (_post.size() != _in.size() || _n <= 0)
        {
            return nullptr;
        }

        typename BinNode<_T>::_BinNodePtr _root = new BinNode<_T>(_post[_n-1]);

        size_t _index = 0;
        for (; _index != _n; ++_index)
        {
            if (_post[_n - 1] == _in[_index])
            {
                break;
            }
        }
        if (_index < 0 || _index >= _n)
        {
            return nullptr;
        }
        vector<_T> _left_tree_post, _left_tree_in, _right_tree_post, _right_tree_in;
        for (size_t _i = 0; _i != _index; _i++)
        {
            _left_tree_post.push_back(_post[_i]);
            _left_tree_in.push_back(_in[_i]);
        }
        for (size_t _i = _index + 1; _i != _in.size(); _i++)
        {
            _right_tree_post.push_back(_post[_i-1]);
            _right_tree_in.push_back(_in[_i]);
        }
        _root->_lc = reconstruction_post_in(_left_tree_post.size(), _left_tree_post, _left_tree_in);
        _root->_rc = reconstruction_post_in(_right_tree_post.size(), _right_tree_post, _right_tree_in);
        return _root;
    }
} //end of Shawn
#endif // end of BINNODE_H
//BinTree.h
#ifndef BINTREE_H
#define BINTREE_H

#include "BinNode.h"
#include <functional>

namespace Shawn
{
    template <typename _T>
    class BinTree                                        //二叉树模板类
    { 
        typedef BinNode<_T>* _BinNodePtr;
        size_t _size; _BinNodePtr _root;                 //规模、根节点
        virtual size_t _updateHeight(_BinNodePtr _x);    //更新节点_x的高度
        void _updateHeightAbove(_BinNodePtr _x);          //更新节点_x及其祖先的高度
    public:
        BinTree() : _size(0), _root(nullptr) { }     //构造函数
        ~BinTree() { if (0 < _size) remove(_root); } //析构函数
        size_t size() const { return _size; }        //规模
        bool empty() const { return !_root; }        //判空
        _BinNodePtr root() const { return _root; }   //树根

        _BinNodePtr insertAsRoot(_T const& _e);                    //插入根节点
        _BinNodePtr insertAsLC(_BinNodePtr _x, _T const& _e);      //e作为x的左孩子(原无)插入
        _BinNodePtr insertAsRC(_BinNodePtr _x, _T const& _e);      //e作为x的右孩子(原无)插入
        _BinNodePtr attachAsLC(_BinNodePtr _x, BinTree<_T>*& _T);  //T作为x左子树接入
        _BinNodePtr attachAsRC(_BinNodePtr _x, BinTree<_T>*& _T);  //T作为x右子树接入
        size_t remove(_BinNodePtr _x);                             //删除以位置x处节点为根的子树,返回该子树原先的规模
        size_t removeAt(_BinNodePtr _x);                           //删除二叉树中位置_x处的节点及其后代,返回被删除节点总数

        //遍历接口:
        template <typename _VST> 
        void travLevel(_VST& _visit) { if (_root) _root->travLevel(_visit); }  //层次遍历
        template <typename _VST> 
        void travPre(_VST& _visit) { if (_root) _root->travPre(_visit); }      //先序遍历
        template <typename _VST> 
        void travIn(_VST& _visit) { if (_root) _root->travIn(_visit); }        //中序遍历
        template <typename _VST> 
        void travPost(_VST& _visit) { if (_root) _root->travPost(_visit); }     //后序遍历

    public:
        //比较器:
        bool operator< (BinTree<_T> const& _t) 
        {
            return _root && _t._root && std::less<_T>(_root, _t._root);
        }
        bool operator== (BinTree<_T> const& _t)
        {
            return _root && _t._root && (_root == _t._root);
        }
        //...
    };  //end of BinTree

    template <typename _T> 
    size_t BinTree<_T>::_updateHeight(_BinNodePtr _x)      //更新节点x高度
    {
        return _x->_height = 1 + max(_x->_lc->stature(), _x->_rc->stature());
    } 

    template <typename _T> 
    void BinTree<_T>::_updateHeightAbove(_BinNodePtr _x)    //从x出发,覆盖历代祖先
    {                                                       //更新整树高度
        while (_x) { _updateHeight(_x); _x = _x->_parent; }
    } 

    template <typename _T> 
    typename BinTree<_T>::_BinNodePtr BinTree<_T>::insertAsRoot(_T const& _e) //将e当作根节点插入空的二叉树
    {
        _size = 1; return _root = new BinNode<_T>(_e);
    } 

    template <typename _T> 
    typename BinTree<_T>::_BinNodePtr BinTree<_T>::insertAsLC(_BinNodePtr _x, _T const& _e)//e插入为x的左孩子
    {
        ++_size; 
        _x->insertAsLC(_e);      //调用的是BinNdoe模板类的insertAsLC函数
        _updateHeightAbove(_x);
        return _x->_lc;
    } 

    template <typename _T>
    typename BinTree<_T>::_BinNodePtr BinTree<_T>::insertAsRC(_BinNodePtr _x, _T const& _e) //e插入为x的右孩子
    {
        ++_size; 
        _x->insertAsRC(_e);   //调用的是BinNdoe模板类的insertAsRC函数
        _updateHeightAbove(_x);
        return _x->_rc;
    } 

    template <typename _T>//二叉树子树接入算法:将_S当作节点_x的左子树接入,_S本身置空
    typename BinTree<_T>::_BinNodePtr BinTree<_T>::attachAsLC(_BinNodePtr _x, BinTree<_T>*& _S)
    { 
        //_x->_lc == nullptr;
        if (_x->_lc = _S->_root) _x->_lc->_parent = _x; //接入
        _size += _S->_size; _updateHeightAbove(_x); //更新全树规模与x所有祖先的高度
        _S->_root = nullptr; _S->_size = 0; _S = nullptr; return _x; //释放原树,返回接入位置
    }

    template <typename _T> //二叉树子树接入算法:将_S当作节点_x的右子树接入,_S本身置空
    typename BinTree<_T>::_BinNodePtr BinTree<_T>::attachAsRC(_BinNodePtr _x, BinTree<_T>*& _S)
    { 
        //_x->_rc == nullptr;
        if (_x->_rc = _S->_root) _x->_rc->_parent = _x;   //接入
        _size += _S->_size; _updateHeightAbove(_x);      //更新全树规模与x所有祖先的高度
        _S->_root = nullptr; _S->_size = 0; _S = nullptr; return _x; //释放原树,返回接入位置
    }

    template<typename _T> //删除二叉树中位置_x处的节点及其后代,返回被删除节点的数值
    size_t BinTree<_T>::remove(_BinNodePtr _x) 
    {   //assert: _x为二叉树中的合法位置
        if (!_x->_parent)        //如果是根节点
        {
            _x = _root = nullptr; size_t _n = _size; _size = 0; return _n;
        }
        else                     //不是根节点,切断来自父节点的指针
        {
            (_x->_parent->_lc == _x) ? _x->_parent->_lc = nullptr : _x->_parent->_rc = nullptr;
            _updateHeightAbove(_x->_parent);   //更新祖先高度
            size_t _n = removeAt(_x); _size -= _n; return _n; //删除子树x,更新规模,返回删除节点总数
        }
    }

    template <typename _T> //删除二叉树中位置x处的节点及其后代,返回被删除节点总数
    size_t BinTree<_T>::removeAt(_BinNodePtr _x)
    {   //assert: x为二叉树中的合法位置
        if (!_x) return 0; //递归基:空树
        size_t _n = 1 + removeAt(_x->_lc) + removeAt(_x->_rc); //递归释放左、右子树
        _x = nullptr; return _n; //释放被摘除节点,并返回删除节点总数
    }


} // end of Shawn
#endif // end of BINTREE_H

//test.cpp
#include<iostream>
#include "BinTree.h"

using namespace std;
using namespace Shawn;
void print(int i)
{
    cout << i << " ";
}

int main()
{
    vector<int> pre{ 1, 2, 4, 7, 3, 5, 6, 8 }, in{ 4, 7, 2, 1, 5, 3, 8, 6 }, post{ 7, 4, 2, 5, 8, 6, 3, 1 };
    size_t n = 8;
    BinNode<int>* root1 = reconstruction_pre_in(n, pre, in);
    BinNode<int>* root2 = reconstruction_post_in(n, post, in);
    root1->travLevel(print);
    cout << endl;
    root2->travLevel(print);
    cout << endl;
    system("pause");
}

猜你喜欢

转载自blog.csdn.net/qq_38216239/article/details/80977021