二叉树的线索化

二叉树结点加上线索的二叉树称为线索二叉树,对二叉树以某种方式(前序、中序、后续)遍历使其变为线索二叉树的过程称为按照该方法对二叉树进行线索化。 在一个二叉树中,当某节点的左指针为空时,令该指针指向按照某种方式遍历二叉树时得到该节点的前驱结点;当某节点的右指针为空时,令该指针指向按照某种方式遍历二叉树时得到该节点的后继结点。结点中指向前驱结点和后继结点的指针称为线索(Thread).
但问题是无法区分:左指针指向的结点是左孩子结点还是前驱结点,右指针指向的结点是右孩子结点还是后继结点。因此需要增加两个线索标志位来区分这两种情况: enum Infor{ LINK, THREAD };

这里写图片描述

#include <iostream>
using namespace std;
enum Infor{ LINK, THREAD };//设置结点的属性
template<typename T>
struct BinaryTreeNodeThd
{   
    BinaryTreeNodeThd(const T& data)
         : _data(data)
         , _pLeft(NULL)
         , _pRight(NULL)
         , _leftThread(LINK)
         , _rightThread(LINK)
         , _pParent(NULL)
    {}
    T _data;
    BinaryTreeNodeThd<T>* _pLeft;
    Infor _leftThread;
    BinaryTreeNodeThd<T>* _pRight;
    Infor _rightThread;
    BinaryTreeNodeThd<T>* _pParent;
};
template<typename T>
class BinaryTreeThd
{
public:
    BinaryTreeThd()
    {}
    BinaryTreeThd(T array[], size_t size)
    {
        size_t index = 0;
        _CreateBinaryTreeThd(_pRoot, array, size, index);
    }
    void PreThread()//前序线索化
    {
        BinaryTreeNodeThd<T>* prev = NULL;
        _PreThread(_pRoot, prev);
    }
    void PreOrder()//前序遍历线索二叉树
    {
        BinaryTreeNodeThd<T>* pCur = _pRoot;
        while (pCur)
        {
            while (pCur && pCur->_leftThread == LINK)
            {
                cout << pCur->_data << " ";
                pCur = pCur->_pLeft;
            }
            cout << pCur->_data << " ";
            pCur = pCur->_pRight;
        }
    }
    void InThread()//中序线索化
    {
        BinaryTreeNodeThd<T>* prev = NULL;
        _InThread(_pRoot, prev);
    }

    void InOrder()//中序遍历线索二叉树
    {
        BinaryTreeNodeThd<T>* pCur = _pRoot;
        while (pCur)
        {
            while (pCur && pCur->_leftThread == LINK)
            {
                pCur = pCur->_pLeft;
            }
            cout << pCur->_data << " ";
            while (pCur && pCur->_rightThread == THREAD)
            {
                pCur = pCur->_pRight;
                cout << pCur->_data << " ";
            }
            if (pCur)
            {
                pCur = pCur->_pRight;
            }
        }
    }
    void PostThread()//后序线索化
    {
        BinaryTreeNodeThd<T>* prev = NULL;
        _PostThread(_pRoot, prev);
    }
    void PostOrder()//后序遍历线索二叉树
    {
        BinaryTreeNodeThd<T>* pCur = _pRoot;
        BinaryTreeNodeThd<T>* prev = NULL;
        while (pCur)
        {
            // 找最左边的结点
            if (pCur->_pLeft != prev)
            {
                while (pCur->_leftThread == LINK)
                    pCur = pCur->_pLeft;
            }
            while (pCur && pCur->_rightThread == THREAD)
            {
                cout << pCur->_data << " ";
                prev = pCur;
                pCur = pCur->_pRight;
            }
            // 左单支的情况
            if (pCur == _pRoot && pCur->_pRight == prev)
            {
                cout << pCur->_data << " ";
                return;
            }
            // 右单支的情况
            while (pCur && pCur->_pRight == prev)
            {
                cout << pCur->_data << " ";
                prev = pCur;
                pCur = pCur->_pParent;
            }
            // 当前节点如果有右子树
            if (pCur && pCur->_rightThread == LINK)
            {
                pCur = pCur->_pRight;
            }
        }
    }
private:
    void _CreateBinaryTreeThd(BinaryTreeNodeThd<T>*& pRoot, T array[], size_t size, size_t& index)
    {
        if (index < size && '#' != array[index])
        {
            pRoot = new BinaryTreeNodeThd<T>(array[index]);
            _CreateBinaryTreeThd(pRoot->_pLeft, array, size, ++index);
            if (pRoot->_pLeft)
            {
                pRoot->_pLeft->_pParent = pRoot;
            }
            _CreateBinaryTreeThd(pRoot->_pRight, array, size, ++index);
            if (pRoot->_pRight)
            {
                pRoot->_pRight->_pParent = pRoot;
            }
        }
    }
    void _PreThread(BinaryTreeNodeThd<T>*& pRoot,BinaryTreeNodeThd<T>*& prev)
    {
        if (pRoot)
        {
            //线索化当前节点的左指针域
            if (NULL == pRoot->_pLeft)
            {
                pRoot->_pLeft = prev;
                pRoot->_leftThread = THREAD;
            }
            //线索化当前节点的前驱节点的右指针域
            if (prev && NULL == prev->_pRight)
            {
                prev->_pRight = pRoot;
                prev->_rightThread = THREAD;
            }
            prev = pRoot;
            if (pRoot->_leftThread == LINK)
                _PreThread(pRoot->_pLeft, prev);
            if (pRoot->_rightThread == LINK)
                _PreThread(pRoot->_pRight, prev);
        }
    }
    void _InThread(BinaryTreeNodeThd<T>*& pRoot, BinaryTreeNodeThd<T>*& prev)
    {
        if (pRoot)
        {
            _InThread(pRoot->_pLeft, prev);
            if (NULL == pRoot->_pLeft)
            {
                pRoot->_pLeft = prev;
                pRoot->_leftThread = THREAD;
            }


            if (prev && NULL == prev->_pRight)
            {
                prev->_pRight = pRoot;
                prev->_rightThread = THREAD;
            }
            prev = pRoot;
            if (pRoot->_rightThread == LINK)
                _InThread(pRoot->_pRight, prev);
        }
    }
    void _PostThread(BinaryTreeNodeThd<T>*& pRoot, BinaryTreeNodeThd<T>*& prev)
    {
        if (pRoot)
        {
            _PostThread(pRoot->_pLeft, prev);
            _PostThread(pRoot->_pRight, prev);

            if (NULL == pRoot->_pLeft)
            {
                pRoot->_pLeft = prev;
                pRoot->_leftThread = THREAD;
            }
            if (prev && NULL == prev->_pRight)
            {
                prev->_pRight = pRoot;
                prev->_rightThread = THREAD;
            }
            prev = pRoot;
        }
    }
private:
    BinaryTreeNodeThd<T>* _pRoot;
};
void FunTest()
{
    //char arr[] {'0','1','3','#','6','#','#','4','#','#','2','5'};
    char arr[] = {'a','b','d','e','f','#','#','g','#','h','#','l','#','#','#','#','c'};
    BinaryTreeThd<char> t(arr, sizeof(arr)/sizeof(arr[0]));
    //t.PreThread();
    //t.PreOrder();
    //t.InThread();
    //t.InOrder();
    t.PostThread();
    t.PostOrder();
}
int main()
{
    FunTest();
    system("pause");
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值