线索化二叉树的创建及遍历

来源:互联网 发布:iphone自动切换网络 编辑:程序博客网 时间:2024/06/05 23:55
#include<stdio.h>#include<iostream>using namespace std;enum thread{    LINK,    THREAD,};template<class T>struct BinaryTreeThdNode{    BinaryTreeThdNode()        :_pLeft(NULL)        ,_pRight(NULL)        ,_pParent(NULL)        ,_leftThread(LINK)        ,_rightThread(LINK)    {}    T _data;    BinaryTreeThdNode* _pLeft;//左孩子    BinaryTreeThdNode* _pRight;//右孩子    BinaryTreeThdNode* _pParent;//双亲节点    enum thread _leftThread;//左索引    enum thread _rightThread;//右索引};template<class T>class BinaryTreeThd{public:    typedef BinaryTreeThdNode<T> Node;    BinaryTreeThd()//线索二叉树的构造        :_pRoot(NULL)    {}    BinaryTreeThd(const T array[],size_t size,T invalid)//线索二叉树的构造    {        size_t index=0;        _pRoot = _CreateTree(_pRoot,array,size,index,invalid);//二叉树的创建    }    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()    {        // 找最左边的节点并访问路径上的节点---访问该最左节点---判断右子树是否为NULL,若为NULL,访问连续后继节点        //若不为NULL,则pCur=pCur->_pRight将右子树重新作为一棵树进行访问        if(_pRoot==NULL)            return;        Node* pCur = _pRoot;        while(pCur)        {            while(pCur->_leftThread == LINK)            {                cout<<pCur->_data<<" ";                pCur = pCur->_pLeft;            }            cout<<pCur->_data<<" ";            //while(pCur->_rightThread == THREAD)// 判断该节点的右子树不存在,访问后继节点            //{            //  pCur = pCur->_pRight;            //  cout<<pCur->_data<<" ";            //}            //if(pCur->_leftThread == LINK)//再访问完后继结点后,可能有两种情况,存在左子树,则先访问左子树,当作新树来处理            //{            //  pCur = pCur->_pLeft;            //}            //if(pCur->_rightThread == LINK)//再访问完后继节点,可能没有左子树,只有右子树,或则最左节点右子树存在,则当作新树处理            //{            //  pCur = pCur->_pRight;            //}            //代码优化---将上面注释起来的代码用下面一句代码替换            pCur = pCur->_pRight;//全部当作新的树来处理        }    }    void InOrder()//中序线索化二叉树的中序遍历    {        // 找到最左端的节点,不访问路径,找到之后访问最左端的节点---再判断其有无右子树,若有,作为新树去处理,若没有,连续访问其后继节点        if(_pRoot==NULL)            return;        Node* pCur = _pRoot;        while(pCur)        {            while(pCur->_leftThread == LINK)            {                pCur = pCur->_pLeft;            }            cout<<pCur->_data<<" ";            while(pCur->_rightThread == THREAD)            {                pCur = pCur->_pRight;                cout<<pCur->_data<<" ";            }            pCur = pCur->_pRight;        }    }    void PostOrder()//后序线索化二叉树的后序遍历    {        //找到最左节点,不访问,首先判断该节点的右子树是否存在,若不存在,访问该节点并到其后继节点,若存在,则访问右子树        //单纯的这样写,会导致死循环问题,在3的地方,原因是6已经访问过了,但pCur=pCur->_pRight还是指向6,接着访问6和3,死循环---解决办法prev标记访问过的        //仅仅是标记过了还是有问题,1没有办法访问到---解决办法,设立双亲节点        //特殊的索引树--左单枝问题,根节点没有访问(最后一个节点的右索引是LINK)---解决办法,if判断        //左单支问题        if(_pRoot==NULL)            return;        Node* pCur = _pRoot;        Node* prev = NULL;//标记访问过的节点        while(pCur)        {            while(pCur->_leftThread == LINK && pCur->_pRight != prev)                pCur = pCur->_pLeft;            while(pCur->_rightThread == THREAD)            {                cout<<pCur->_data<<" ";                prev = pCur;                pCur = pCur->_pRight;            }            if(pCur==_pRoot && pCur->_pRight==NULL)            {                cout<<pCur->_data<<" ";                return ;            }            while(pCur && pCur->_pRight==prev)            {                cout<<pCur->_data<<" ";                prev = pCur;                pCur = pCur->_pParent;            }            if(pCur && pCur->_pRight != prev)            pCur = pCur->_pRight;        }    }private:    //底层实现    Node* _CreateTree(Node* pRoot,const T array[],size_t size,size_t& index,T& invalid)//二叉树的创建    {        if(index<size && array[index]!=invalid)        {            pRoot = new Node;            pRoot->_data = array[index];            pRoot->_pLeft = _CreateTree(pRoot->_pLeft,array,size,++index,invalid);            if(pRoot->_pLeft)                pRoot->_pLeft->_pParent = pRoot;            pRoot->_pRight = _CreateTree(pRoot->_pRight,array,size,++index,invalid);            if(pRoot->_pRight)                pRoot->_pRight->_pParent = pRoot;        }        return pRoot;    }    void _PreThreading(Node* pRoot,Node*& prev)//前序线索化---采用先线索化根节点,判断根节点左右子树是否存在,再利用递归线索化左子树和右子树的的节点    {        if(pRoot)        {            if(pRoot->_pLeft == NULL)// 线索化当前指针的左指针域            {                pRoot->_pLeft = prev;                pRoot->_leftThread = THREAD;            }            if(prev!=NULL && prev->_pRight==NULL)//线索化前一个节点的右指针域            {                prev->_pRight = pRoot;                prev->_rightThread = THREAD;            }            prev=pRoot;            if(pRoot->_leftThread != THREAD)//防止索引后陷入死循环            _PreThreading(pRoot->_pLeft,prev);            if(pRoot->_rightThread != THREAD)            _PreThreading(pRoot->_pRight,prev);        }    }    void _InThreading(Node* pRoot,Node*& prev)//中序线索化    {        if(pRoot)        {            _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 != THREAD)                _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 funtest(){    char str[] = {"124###35##6"};    char invalid = '#';    BinaryTreeThd<char> t;    BinaryTreeThd<char> t1(str,strlen(str),invalid);//测试线索二叉树的创建    //t1.PreThreading();//测试线索二叉树的先序索引    //t1.InThreading();//测试线索二叉树的中序索引    //t1.PostThreading();//测试线索二叉树的后序线索}void funtest1()//测试前序索引二叉树的前序遍历{    char str[] = {"124###35##6"};    char invalid = '#';    BinaryTreeThd<char> t;    BinaryTreeThd<char> t1(str,strlen(str),invalid);    t1.PreThreading();    t1.PreOrder();}void funtest2()//测试中序索引二叉树的中序遍历{    char str[] = {"124###35##6"};    char invalid = '#';    BinaryTreeThd<char> t;    BinaryTreeThd<char> t1(str,strlen(str),invalid);//测试线索二叉树的创建    t1.InThreading();    t1.InOrder();}void funtest3()//测试后序索引二叉树的后序遍历{    //char str[] = {"124###35##6"};    char str[] = {"12#3##45#6#7##8"};    char invalid = '#';    BinaryTreeThd<char> t;    BinaryTreeThd<char> t1(str,strlen(str),invalid);//测试线索二叉树的创建    t1.PostThreading();    t1.PostOrder();}int main(){    //funtest();    //funtest1();    //funtest2();    funtest3();    getchar();    return 0;}
0 0
原创粉丝点击