二叉树线索化

来源:互联网 发布:django网站开发源码 编辑:程序博客网 时间:2024/06/06 00:06

/*
名称:二叉树线索化
说明:这个东西,一开始弄起来,我去,感觉老复杂了。照着书上看了好久,愣是没看懂,照着敲了一遍,又手动模拟推了一遍,有了一点思路。照着把后序的线索化和遍历也敲出来了。

这里要注意的是:对于中序来说,其能线索化后访问到其前驱和后继(可以理解为不通过栈访问到),而对于后序来说,其只能不通过栈访问到其后继(这也是我后序遍历敲的是倒序的原因),要想访问到其后继只能通过一般的递归或使用栈的方法。同理,先序遍历也只能访问到其后继。

*/

//线索化结点typedef struct ThreadNode{    int data;    ThreadNode *lchild,*rchild;    int ltag,rtag;}ThreadNode,*ThreadTree;//创建二叉树(未线索化)void CreateThreadTree(ThreadTree &T){    int val;    cin>>val;    if(val == -1)    {        T = NULL;    }    else    {        T = new ThreadNode;        T->data = val;        T->ltag = 0;        T->rchild = 0;        CreateThreadTree(T->lchild);        CreateThreadTree(T->rchild);    }}//中序线索化void InThread(ThreadTree &p,ThreadTree &pre)    //pre是先序结点,p是当前节点{    if(p!=NULL)    {        InThread(p->lchild,pre);        //递归左子树        if(p->lchild == NULL)   //当前结点的左子树为空        {            p->lchild = pre;            p->ltag = 1;        }        if(pre !=NULL && pre->rchild == NULL)    //当前结点的右子树为空        {            pre->rchild = p;            pre->rtag = 1;        }        pre = p;        InThread(p->rchild,pre);    //递归右子树    }}//递归遍历创建中序线索二叉树void CreateInThread(ThreadTree T){    ThreadTree pre = NULL;    if(T!=NULL)    {        InThread(T,pre);        pre->rchild = NULL;        pre->rtag = 1;    }}//递归输出中序线索化二叉树void ThreadInOrder(ThreadTree T){    if(T != NULL)    {        ThreadInOrder(T->lchild);        cout<<T->data<<" "<<T->ltag<<"--"<<T->rtag<<endl;        ThreadInOrder(T->rchild);    }}//求中序线索化后以p为根节点的树的中序线索化的第一个结点//即以p为根节点的树的最左下角的结点ThreadNode* FirstNode(ThreadNode *p){    while(p->ltag == 0)        p = p->lchild;      //一直向左下角前进,知道p无左子树    return p;}//求中序线索化后p的后继节点ThreadNode* NextNode(ThreadNode *p){    if(p->rtag == 1)      //如果p无右子树的话,线索化后的p结点的右指针即指向其后继节点        return p->rchild;    else    {        p = FirstNode(p->rchild);       //如果p有右子树的话,则以p右孩子为树的第一个结点就是其后继结点        return p;    }}//非递归中序遍历线索二叉树(不需要用到栈)void ThreadInOrder1(ThreadNode *T){    for(ThreadNode *p = FirstNode(T);p != NULL;p = NextNode(p))    {        cout<<p->data<<" ";    }}//后序线索化void PostThread(ThreadTree &p,ThreadTree &pre){    ThreadNode *q;    if(p != NULL)    {        PostThread(p->lchild,pre);        PostThread(p->rchild,pre);        if(p->lchild == NULL)        {            p->ltag = 1;       //打上线索化标志            p->lchild = pre;        }        if(pre != NULL && pre->rchild != NULL)     //pre指向上一次递归中的结点,即上一个结点        {            pre->rtag = 1;        //打上线索化标志            pre->rchild = p;        }        pre = p;    }}//后序创建线索化二叉树void CreatePostThread(ThreadTree T){    ThreadTree pre = NULL;    if(T != NULL)    {        PostThread(T,pre);    }}//求后序线索化后结点p的前驱结点ThreadNode* PreNode(ThreadTree p){    if(p != NULL)    {        if(p->ltag == 1)            return p->lchild;        else        {            if(p->rchild != NULL)                return p->rchild;            else                return p->lchild;        }    }}//后序遍历二叉树(倒序遍历非递归)void ThreadPostOrder2(ThreadTree T){    for(ThreadNode *p = T; p != NULL;p = PreNode(p))    {        cout<<p->data<<" ";    }}