二叉树线索化

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

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

*/

//线索化结点
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<<" ";
    }
}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值