二叉树的线索化

来源:互联网 发布:知乎气功 编辑:程序博客网 时间:2024/06/06 00:53

什么是线索化

在前面二叉树的遍历中我们可以了解到,二叉树的先序、中序、后序、层序遍历,所以我们都知道当以二叉树链表作为存储结构时,只能找到结点的左、右孩子信息,而不能直接得到结点在任一序列中的前驱和后继信息,这种信息只有在遍历的动态过程中才能得到。
所以我们能想到的最简单的办法是在每个结点上增加两个指针雨fwd和bkwd,分别指示结点在任一序列遍历时得到的前驱和后继信息。这样可以大大降低存储空间密度;另一方面,在有n个结点的二叉链表中必定存在n+1个空指针域,由此就可以存放它的前驱和后继的信息。
所以:若结点有左子树,则其lchild域指示器左孩子,否则令lchild域指示其前驱;若结点有右子树,则其rchild域指示其右孩子,否则令rchild域指示其后继。为此增加了两个标志域:

这里写图片描述
以这种结点结构构成的二叉链表作为二叉树的存储结构,叫做线索链表;

构建线索化二叉树

先序构建线索化二叉树:
我们在构建结点的时候,所有用来标记线索化的指针域全部设为LINK;所以,在构建线索化二叉树时,需要将线索化的结点改为THREAD,其实在构建二叉树的时候就是找到所有的叶子结点,然后进行修改,前驱在寻找的时候只需要将结点的上一个结点保存起来,到时候用前驱指向就可以了,后继就比较困难了;下图可以看到,prev的后继就是pRoot 所以:
这里写图片描述
以下是先序构建线索二叉树的代码:

enum PointFlag{LINK, THREAD};  //LINK表示结点,THREAD表示线索化template<class T>struct BinaryTreeNodeThd {    BinaryTreeNodeThd(const T& data)        : _data(data)        , _pLeft(NULL)        , _pRight(NULL)        , _parent(NULL)        , _leftThread(LINK)        , _rightThread(LINK)    {}    T _data;    BinaryTreeNodeThd<T>* _pLeft;    BinaryTreeNodeThd<T>* _pRight;    BinaryTreeNodeThd<T>* _parent;    PointFlag _leftThread;    PointFlag _rightThread;};void _PreThreading(Node* pRoot, Node*& Prev)    {        if (NULL != pRoot)        {            //遍历根结点            if (NULL == pRoot->_pLeft)//找到最左边的结点            {                pRoot->_pLeft = Prev; //将前驱赋给它                pRoot->_leftThread = THREAD; //将它的改为THREAD            }            if (Prev && Prev->_pRight == NULL) //Prev是pRoot的前一个结点, 前驱就用两者的关系解决            {                Prev->_pRight = pRoot;                Prev->_rightThread = THREAD;            }            Prev = pRoot; //将Prev的值修改掉            //递归遍历左子树            if (pRoot->_leftThread == LINK)                _PreThreading(pRoot->_pLeft, Prev);            //递归遍历右子树            if (pRoot->_rightThread == LINK)                _PreThreading(pRoot->_pRight, Prev);        }    }

完整版代码:

#include<iostream>using namespace std;enum PointFlag{LINK, THREAD};  //LINK表示结点,THREAD表示线索化template<class T>struct BinaryTreeNodeThd {    BinaryTreeNodeThd(const T& data)        : _data(data)        , _pLeft(NULL)        , _pRight(NULL)        , _parent(NULL)        , _leftThread(LINK)        , _rightThread(LINK)    {}    T _data;    BinaryTreeNodeThd<T>* _pLeft;    BinaryTreeNodeThd<T>* _pRight;    BinaryTreeNodeThd<T>* _parent;    PointFlag _leftThread;    PointFlag _rightThread;};template<class T>class BinaryTreeThd{    typedef BinaryTreeNodeThd<T> Node;public:    BinaryTreeThd()        : _pRoot(NULL)    {}    BinaryTreeThd(const T array[], size_t size, const T& invalid)    {        size_t idx = 0;        Node* parent = NULL;        _CreatTree(_pRoot, array, size, idx, invalid, parent);    }    void PreThreading() //前序构建线索二叉树    {        Node* prev = NULL;        _PreThreading(_pRoot, prev);    }    void InThreading() //中序构建线索二叉树    {        Node* prev = NULL;        _InThreading(_pRoot, prev);    }    void PostThreading() //后序构建线索二叉树    {        Node* prev = NULL;        _PostThreading(_pRoot, prev);    }    void PreOrder()    {        Node* pCur = _pRoot;        while (pCur)        {            while (pCur->_leftThread == LINK)            {                cout << pCur->_data << " ";                pCur = pCur->_pLeft;            }            cout << pCur->_data << " ";            pCur = pCur->_pRight;/*          while (pCur->_rightThread == THREAD)            {                pCur = pCur->_pRight;                cout << pCur->_data << " ";            }            if (pCur->_leftThread == LINK)                pCur = pCur->_pLeft;            else                pCur = pCur->_pRight;*/        }    }    void InOrder()    {        Node* pCur = _pRoot;        while (pCur)        {            while (pCur->_leftThread == LINK)            {                pCur = pCur->_pLeft;            }            cout << pCur->_data << " ";            while (pCur && pCur->_rightThread == THREAD)            {                pCur = pCur->_pRight;                if (pCur)                    cout << pCur->_data << " ";            }            if (pCur)                pCur = pCur->_pRight;        }    }    void PostOrder()    {        Node* pCur = _pRoot;        Node* prev = NULL;        while (pCur)        {            while (pCur->_pLeft != prev && pCur->_leftThread == LINK)//找到最左边的结点                pCur = pCur->_pLeft;            while (pCur && pCur->_rightThread == THREAD)//判断结点的右子树是否为线索            {                cout << pCur->_data << " ";                prev = pCur;                pCur = pCur->_pRight;            }            if (_pRoot == pCur)  //判断是否为根结点, 左单只的情况            {                cout << pCur->_data << endl;                return;            }            while (pCur && pCur->_pRight == prev)            {                cout << pCur->_data << " ";                prev = pCur;                pCur = pCur->_parent;            }            if (pCur && pCur->_rightThread == LINK)                pCur = pCur->_pRight;        }    }private:    void _CreatTree(Node*& pRoot, const T array[], size_t size, size_t &idx, const T& invalid, Node*& parent)    {        if (idx < size && array[idx] != invalid)        {            pRoot = new Node(array[idx]);            pRoot->_parent = parent;            _CreatTree(pRoot->_pLeft, array, size, ++idx, invalid, pRoot);            _CreatTree(pRoot->_pRight, array, size, ++idx, invalid, pRoot);        }    }    void _PreThreading(Node* pRoot, Node*& Prev)    {        if (NULL != pRoot)        {            //遍历根结点            if (NULL == pRoot->_pLeft)//找到最左边的结点            {                pRoot->_pLeft = Prev; //将前驱赋给它                pRoot->_leftThread = THREAD; //将它的改为THREAD            }            if (Prev && Prev->_pRight == NULL) //Prev是pRoot的前一个结点, 前驱就用两者的关系解决            {                Prev->_pRight = pRoot;                Prev->_rightThread = THREAD;            }            Prev = pRoot; //将Prev的值修改掉            //递归遍历左子树            if (pRoot->_leftThread == LINK)                _PreThreading(pRoot->_pLeft, Prev);            //递归遍历右子树            if (pRoot->_rightThread == LINK)                _PreThreading(pRoot->_pRight, Prev);        }    }    void _InThreading(Node* pRoot, Node*& Prev)    {        if (pRoot != NULL)        {            _InThreading(pRoot->_pLeft, Prev);            if (pRoot->_pLeft == NULL)            {                pRoot->_pLeft = Prev;                pRoot->_leftThread = THREAD;            }            if (Prev && Prev->_pRight == NULL)            {                Prev->_pRight = pRoot;                Prev->_rightThread = THREAD;            }            Prev = pRoot;            if (pRoot->_rightThread == LINK)            {                _InThreading(pRoot->_pRight, Prev);            }        }    }    void _PostThreading(Node* pRoot, Node*& Prev)    {        if (pRoot)        {            _PostThreading(pRoot->_pLeft, Prev);            _PostThreading(pRoot->_pRight, Prev);            if (pRoot->_pLeft == NULL)            {                pRoot->_pLeft = Prev;                pRoot->_leftThread = THREAD;            }            if (Prev && Prev->_pRight == NULL)            {                Prev->_pRight = pRoot;                Prev->_rightThread = THREAD;            }            Prev = pRoot;        }    }private:    Node* _pRoot;};void Test(){    char array[] = "124###35##6";    BinaryTreeThd<char> b(array, strlen(array), '#');    //b.PreThreading();    //b.InThreading();    b.PostThreading();    //b.PreOrder();    //b.InOrder();    b.PostOrder();}int main(){    Test();    return 0;}
原创粉丝点击