二叉查找树的前序遍历,后序遍历和中序遍历互求算法模板

遍历模板


其实这个问题想清楚了很简单,只要把这三个概念理解透彻就可以做出来了,比如前序遍历的第一个值一定是根节点,然后这个根节点对应到中序遍历里面,在中序遍历的这个值的两边的值,一定在以此节点为根节点的两个子树上,同理,后序遍历也一样。

已知前序遍历和后序遍历是不能求唯一的中序遍历树的。

 

#include <iostream>
#include <string>

using std::string;

template<typename _Val>
struct TreeNodeBase
{
    TreeNodeBase<_Val> *left;
    TreeNodeBase<_Val> *right;
    _Val val;
};

//已知前序遍历和中序遍历,找后序遍历
template<typename _Iter, typename _sizeType, typename _TreeNodeType = TreeNodeBase<char>>
_TreeNodeType *preOrderInfixOrderToSufixOrder(_Iter &pre, _Iter &in, _sizeType length)
{
    if (length == 0)
        return nullptr;

    auto node = new _TreeNodeType;
    
    _sizeType index = 0;

    for (; index != length; index++)//找到对应的前序遍历的点
        if (*(in + index) == *(pre))
            break;

    node->left = preOrderInfixOrderToSufixOrder(pre + 1, in, index);
    node->right = preOrderInfixOrderToSufixOrder(pre + index + 1, in + index + 1, length - (index + 1));
    node->val = *pre;
    std::cout << node->val << " ";
    return node;
}

//已知后序遍历和中序遍历,找前序遍历
template<typename _Iter, typename _sizeType, typename _TreeNodeType = TreeNodeBase<char>>
_TreeNodeType *sufixOrderInfixOrderToPreOrder(_Iter &sufix, _Iter &in, _sizeType length)
{
    if (length == 0)
        return nullptr;
    auto node = new _TreeNodeType;
    node->val = *(sufix + length - 1);
    std::cout << node->val << " ";

    _sizeType index = 0;
    for (;index != length ;index++)
        if (*(in + index) == *(sufix + length - 1))
            break;
    node->left = sufixOrderInfixOrderToPreOrder(sufix, in, index);
    node->right = sufixOrderInfixOrderToPreOrder(sufix + index, in + index + 1, length - (index + 1));

    return node;
}

//已知前序遍历/后序遍历 + 中序遍历求后序遍历/前序遍历
/*int main()
{
    string preOrder("GDAFEMHZ");
    string infixOrder("ADEFGHMZ");
    string sufixOrder("AEFDHZMG");

    auto root1 = preOrderInfixOrderToSufixOrder(preOrder.begin(), infixOrder.begin(), preOrder.size());
    std::cout << std::endl;
    auto root2 = sufixOrderInfixOrderToPreOrder(sufixOrder.begin(), infixOrder.begin(), preOrder.size());

    system("pause");
    return 0;
}*/

 

线索二叉树与前序遍历,后序遍历,中序遍历的联系


线索二叉树是利用了二叉树中的null节点,在遍历二叉树时,如果我们要找一个子节点的前继和后序,往往我们只能通过递归的方法,但是用了线索二叉树以后就不用了,直接while循环就可以了(注意后序线索二叉树不可以,必须要辅助栈)

写了个C++模板来玩:

    typedef enum { Node, Thread } ChildType;

    struct __trueType{ };
    struct __falseType { };

    template<typename _Val>
    struct TreeNodeBase
    {
        typedef __falseType __isThreadingTree;
        TreeNodeBase() 
            :left(nullptr), right(nullptr), val(0) { }
        _Val val;

        void *left, *right;
        virtual ~TreeNodeBase() { }
    };

    template<typename _Val>
    struct ThreadingTreeNodeBase :public TreeNodeBase<_Val>
    {
        typedef __trueType __isThreadingTree;
        ThreadingTreeNodeBase()
            :leftType(ChildType::Node),rightType(ChildType::Node){ }

        ThreadingTreeNodeBase<_Val> *left;
        ThreadingTreeNodeBase<_Val> *right;
        ChildType leftType, rightType;
        ~ThreadingTreeNodeBase() { }
    };

    template<typename _TnBase>
    class TreeHelper final
    {
    public:
        inline static void createInOrderThreadingTree(_TnBase *root);
        inline static void createPreOrderThreadingTree(_TnBase *root);
        inline static void createSufixOrderThreadingTree(_TnBase *root);

        static void inOrderShow(std::ostream &os, _TnBase *root);
        static void preOrderShow(std::ostream &os, _TnBase *root);
        static void sufixOrderShow(std::ostream &os, _TnBase *const root);

        template<typename _Iter, typename _sizeType>
        inline static _TnBase *preOrderInfixOrderToSufixOrder(_Iter &pre, _Iter &in, _sizeType length);

        static void setOstream(std::ostream &os) { _os = os; }
        static std::ostream &getOstream() { return _os; }
    private:
        template<typename _Iter, typename _sizeType>
        inline static _TnBase *preOrderInfixOrderToSufixOrderPirvate(_Iter &pre, _Iter &in, _sizeType length, __trueType);
        template<typename _Iter, typename _sizeType>
        static _TnBase *preOrderInfixOrderToSufixOrderPirvate1(_Iter &pre, _Iter &in, _sizeType length, __trueType);

        template<typename _Iter, typename _sizeType>
        inline static _TnBase *preOrderInfixOrderToSufixOrderPirvate(_Iter &pre, _Iter &in, _sizeType length, __falseType);
        template<typename _Iter, typename _sizeType>
        static _TnBase *preOrderInfixOrderToSufixOrderPirvate1(_Iter &pre, _Iter &in, _sizeType length, __falseType);

        static void createInOrderThreadingTreePrivate(_TnBase *root, _TnBase *&_preNode);
        static void createPreOrderThreadingTreePrivate(_TnBase *root, _TnBase *&_preNode);
        static void createSufixOrderThreadingTreePrivate(_TnBase *root, _TnBase *&_preNode);

        static _TnBase *_preNode;
        static std::ostream &_os;

        static void clearNodeType(_TnBase *root);

        TreeHelper() = delete;
        TreeHelper(const TreeHelper< _TnBase> &) = delete;
        TreeHelper(TreeHelper< _TnBase> &&) = delete;
    };

    template<typename _TnBase>
    void TreeHelper<_TnBase>::inOrderShow(std::ostream &os, _TnBase *root)
    {
        if (root == nullptr)
            return;

        while (root)
        {
            while (root->leftType == ChildType::Node)
                root = reinterpret_cast<_TnBase *>(root->left);
            while (root != nullptr)
            {
                os << root->val << " ";
                if (root->rightType == ChildType::Thread)
                    root = reinterpret_cast<_TnBase *>(root->right);
                else
                {
                    root = reinterpret_cast<_TnBase *>(root->right);
                    while (root->leftType == ChildType::Node)
                        root = reinterpret_cast<_TnBase *>(root->left);
                }
            }
        }
    }

    template<typename _TnBase>
    void TreeHelper<_TnBase>::preOrderShow(std::ostream &os, _TnBase *root)
    {
        if (root == nullptr)
            return;

        while (root)
        {
            while (root != nullptr)
            {
                os << root->val << " ";
                if (root->rightType == ChildType::Thread)
                    root = reinterpret_cast<_TnBase *>(root->right);
                else
                    root = root->leftType == ChildType::Node ? 
                    reinterpret_cast<_TnBase *>(root->left) : reinterpret_cast<_TnBase *>(root->right);
            }
        }
    }

    template<typename _TnBase>
    void TreeHelper<_TnBase>::sufixOrderShow(std::ostream &os, _TnBase *const root)
    {
        //注意:后序遍历不能真正通过线索走完所有节点,要用栈
        if (root == nullptr)
            return;

        _TnBase *p = root;

        using std::stack;
        stack<_TnBase *> s;

        _TnBase *pre = nullptr;

        while (true)
        {
            while (p->leftType != ChildType::Thread)
            {
                if (p->leftType == ChildType::Node &&  p->rightType == ChildType::Node)
                    s.push(p);
                p = reinterpret_cast<_TnBase *>(p->left);
            }

            //pre节点跟踪右节点的情况
            while (p && p->rightType == ChildType::Thread)
            {
                os << p->val << " ";
                pre = reinterpret_cast<_TnBase *>(p);
                p = reinterpret_cast<_TnBase *>(p->right);
            }
                
            while (p->right == pre && !s.empty())
            {
                os << p->val << " ";
                pre = p;
                s.pop();
                if (!s.empty())
                    p = s.top();
            }
            if (s.empty())
                break;

            if (p != nullptr && p->rightType != ChildType::Thread)
                p = reinterpret_cast<_TnBase *>(p->right);
        }

    }

    template<typename _TnBase> std::ostream &TreeHelper<_TnBase>::_os = std::cout;

    template<typename _TnBase>
    void TreeHelper<_TnBase>::clearNodeType(_TnBase *root)
    {
        if (root->leftType == ChildType::Thread)
        {
            root->leftType = ChildType::Node;
            root->left = nullptr;
        }
        if (root->rightType == ChildType::Thread)
        {
            root->rightType = ChildType::Node;
            root->right = nullptr;
        }
    }

    template<typename _TnBase>
    void TreeHelper<_TnBase>::createInOrderThreadingTree(_TnBase *root)
    {
        _TnBase *_preNode = root;
        createInOrderThreadingTreePrivate(root, _preNode);

        if (_preNode->right == nullptr)
            _preNode->rightType = ChildType::Thread;
    }

    template<typename _TnBase>
    void TreeHelper<_TnBase>::createPreOrderThreadingTree(_TnBase *root)
    {
        _TnBase *_preNode = root;
        createPreOrderThreadingTreePrivate(root, _preNode);

        if (_preNode->right == nullptr)
            _preNode->rightType = ChildType::Thread;
    }

    template<typename _TnBase>
    void TreeHelper<_TnBase>::createSufixOrderThreadingTree(_TnBase *root)
    {
        _TnBase *_preNode = nullptr;
        createSufixOrderThreadingTreePrivate(root, _preNode);

        if (_preNode->right == nullptr)
            _preNode->rightType = ChildType::Thread;
    }

    template<typename _TnBase>
    void TreeHelper<_TnBase>::createInOrderThreadingTreePrivate(_TnBase *root, _TnBase *&_preNode)
    {
        if (root == nullptr)
            return;
        clearNodeType(root);

        if (root->leftType != ChildType::Thread)
            createInOrderThreadingTreePrivate(reinterpret_cast<_TnBase *>(root->left), _preNode);
        if (root->left == nullptr)
        {
            root->leftType = ChildType::Thread;
            root->left = _preNode;
        }

        if (_preNode->right == nullptr)
        {
            _preNode->rightType = ChildType::Thread;
            _preNode->right = root;
        }
        _preNode = root;
        if (root->rightType != ChildType::Thread)
            createInOrderThreadingTreePrivate(reinterpret_cast<_TnBase *>(root->right), _preNode);
    }

    template<typename _TnBase>
    void TreeHelper<_TnBase>::createPreOrderThreadingTreePrivate(_TnBase *root, _TnBase *&_preNode)
    {
        if (root == nullptr)
            return;
        clearNodeType(root);

        if (root->left == nullptr)
        {
            root->leftType = ChildType::Thread;
            root->left = _preNode;
        }

        if (_preNode->right == nullptr)
        {
            _preNode->rightType = ChildType::Thread;
            _preNode->right = root;
        }

        _preNode = root;
        if (root->leftType != ChildType::Thread)
            createPreOrderThreadingTreePrivate(reinterpret_cast<_TnBase *>(root->left), _preNode);
        
        if (root->rightType != ChildType::Thread)
            createPreOrderThreadingTreePrivate(reinterpret_cast<_TnBase *>(root->right), _preNode);
    }

    template<typename _TnBase>
    void TreeHelper<_TnBase>::createSufixOrderThreadingTreePrivate(_TnBase *root, _TnBase *&_preNode)
    {
        if (root == nullptr)
            return;
        clearNodeType(root);

        if (root->leftType != ChildType::Thread)
            createSufixOrderThreadingTreePrivate(reinterpret_cast<_TnBase *>(root->left), _preNode);

        if (root->rightType != ChildType::Thread)
            createSufixOrderThreadingTreePrivate(reinterpret_cast<_TnBase *>(root->right), _preNode);

        if (root->left == nullptr)
        {
            root->leftType = ChildType::Thread;
            root->left = _preNode;
        }

        if (_preNode != nullptr && _preNode->right == nullptr)
        {
            _preNode->rightType = ChildType::Thread;
            _preNode->right = root;
        }

        _preNode = root;
    }

    template<typename _TnBase>
    template<typename _Iter, typename _sizeType>
    inline _TnBase *TreeHelper<_TnBase>::preOrderInfixOrderToSufixOrder(_Iter &pre, _Iter &in, _sizeType length)
    {
        return preOrderInfixOrderToSufixOrderPirvate(pre, in, length, _TnBase::__isThreadingTree());
    }

    template<typename _TnBase>
    template<typename _Iter, typename _sizeType>
    inline static _TnBase *
        TreeHelper<_TnBase>::preOrderInfixOrderToSufixOrderPirvate(_Iter &pre, _Iter &in, _sizeType length, __trueType)
    {
        return preOrderInfixOrderToSufixOrderPirvate1(pre, in, length, __trueType());
    }

    template<typename _TnBase>
    template<typename _Iter, typename _sizeType>
    inline static _TnBase *
        TreeHelper<_TnBase>::preOrderInfixOrderToSufixOrderPirvate(_Iter &pre, _Iter &in, _sizeType length, __falseType)
    {
        return preOrderInfixOrderToSufixOrderPirvate1(pre, in, length, __falseType());
    }

    template<typename _TnBase>
    template<typename _Iter, typename _sizeType>
    _TnBase *TreeHelper<_TnBase>::preOrderInfixOrderToSufixOrderPirvate1(_Iter &pre, _Iter &in, _sizeType length, __trueType)
    {
        if (length == 0)
            return nullptr;

        auto node = new _TnBase;
        _sizeType index = 0;

        for (; index != length; index++)//找到对应的前序遍历的点
            if (*(in + index) == *(pre))
                break;

        node->left = preOrderInfixOrderToSufixOrderPirvate1(pre + 1, in, index, __trueType());
        node->right = preOrderInfixOrderToSufixOrderPirvate1(pre + index + 1, in + index + 1, length - (index + 1), __trueType());
        node->val = *pre;
        _os << node->val << " ";
        return node;
    }

    template<typename _TnBase>
    template<typename _Iter, typename _sizeType>
    _TnBase *TreeHelper<_TnBase>::preOrderInfixOrderToSufixOrderPirvate1(_Iter &pre, _Iter &in, _sizeType length, __falseType)
    {
        if (length == 0)
            return nullptr;

        auto node = new _TnBase;

        _sizeType index = 0;

        for (; index != length; index++)//找到对应的前序遍历的点
            if (*(in + index) == *(pre))
                break;

        node->left = preOrderInfixOrderToSufixOrderPirvate1(pre + 1, in, index, __falseType());
        node->right = preOrderInfixOrderToSufixOrderPirvate1(pre + index + 1, in + index + 1, length - (index + 1), __falseType());
        node->val = *pre;
        _os << node->val << " ";
        return node;
    }
原文地址:https://www.cnblogs.com/Philip-Tell-Truth/p/6619136.html