二叉树的(先,中,后)序建树,线索化及遍历(三)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_39956356/article/details/80142461

(先序,中序)线索化及遍历

由于篇幅的原因,这里仅仅展示(先序,中序)线索化及遍历,主要原因这两个有很高的相识度,思想几乎一样。仅仅是访问顺序不同!!!
接下来都是按先序操作实现功能(整体流程),中序操作实现功能(整体流程),后序操作实现功能(整体流程)。即一个一个讲完整在进行下一个。
后序线索化及遍历(我的下篇文章):

首先,不管在哪种线索化,都需要一个pre指针指向上次访问的结点,因为我们的目的是找到前驱和后继,那么就肯定需要两个指针(一前一后)。

一:先序线索化及遍历

递归与先序访问顺序

先序访问顺序
这里写图片描述

对应代码
//先序线索化
void PreThreading(BiThrTree p)
{
    if (p)
    {
        if (!p->lchild)                                     //前驱线索
        {
            p->lchild = pre;
            p->LTag = Thread;
        }
        if (pre != NULL && !pre->rchild)                    //后继线索
        {
            pre->rchild = p;
            pre->RTag = Thread;
        }
        pre = p;
        if(p->LTag == Link)
            PreThreading(p->lchild);                        //左子树线索化
        if (p->RTag == Link)
            PreThreading(p->rchild);                        //右子树线索化
    }
}

2:先序线索化添加虚设头结点(建立双向循环链表)

作用:规范,方便,忠实数据结构书上的的做法(转一圈就结束),如果你觉得麻烦,不加也可以,但必须了解其遍历的前因后果,以便知道遍历结束的循环出口。

这里写图片描述

对应代码
//先序线索化二叉树(添加头结点)建立双向循环链表
Status PreOrderThreading(BiThrTree &Thrt, BiThrTree T)
{
    if (!(Thrt = (BiThrTree)malloc(sizeof(BiThrNode))))
        return OVERFLOW;
    Thrt->LTag = Link;  Thrt->RTag = Thread;                //左指针指向头结点
    Thrt->rchild = Thrt;                                    //右指针回指   
    if (!T)
        Thrt->lchild = Thrt;                                //二叉树为空,左指针回指
    else
    {
        Thrt->lchild = T;   pre = Thrt;                     //虚设头节点指向头节点
        PreThreading(T);
        pre->rchild = Thrt;  pre->RTag = Thread;            //处理最后一个节点指向虚设头结点
        Thrt->rchild = pre;
    }
    return OK;
}

3:先序线索化遍历

先序线索化遍历前驱与后继图
这里写图片描述

核心思想:递归与访问顺序

1:如果你不添加虚设的头结点,也可以利用先序线索化的唯一NULL(G->rchild)作为循环出口
2:这里需要注意如果使用先序线索化就要用先序线索化遍历
这里写图片描述

对应代码
//先序遍历--必须要先序线索化
Status PreOrderTraverse(BiThrTree HeadNode, Status(*visit)(TElemType e))
{
    BiThrTree p = HeadNode->lchild;                                 //虚设头结点指向根节点
    while (p != HeadNode)                                           //转一圈回来结束
    {
        while (p->lchild != NULL && p->LTag == Link)                //先序一直向左走
        {
            visit(p->data);                                         //1:访问根节点
            p = p->lchild;                                          //向左走
        }
        visit(p->data);                                             //2:访问最左边节点
        if(p->LTag == Thread)                                       //3:遍历右子树(如果有子树,则返回215行,往左走)
            p = p->rchild;                              
    }
    return OK;
}
先序线索化及遍历输出结果

这里写图片描述

二:中序线索化及遍历

1:中序线索化

递归与先序访问顺序

这里写图片描述

这里写图片描述

对应代码
//中序线索化
void InThreading(BiThrTree p)
{
    if (p)
    {
        InThreading(p->lchild);             //左子树线索化
        if (!p->lchild)                     //前驱线索
        {
            p->LTag = Thread;
            p->lchild = pre;
        }
        if (!pre->rchild)                   //后继线索
        {
            pre->RTag = Thread;
            pre->rchild = p;
        }
        pre = p;
        InThreading(p->rchild);             //右子树线索化
    }
}

2:先序线索化添加虚设头结点(建立双向循环链表)

作用:规范,方便,忠实数据结构书上的的做法(转一圈就结束),如果你觉得麻烦,不加也可以,但必须了解其遍历的前因后果,以便知道遍历结束的循环出口。

这里写图片描述

对应代码
//中序线索化二叉树(添加头结点)--双向链表
Status InOrderThreading(BiThrTree &Thrt, BiThrTree T)
{
    if(!(Thrt = (BiThrTree)malloc(sizeof(BiThrNode))))      //虚设根节点
        return OVERFLOW;
    Thrt->LTag = Link;  Thrt->RTag = Thread;                //左指针指向头结点
    Thrt->rchild = Thrt;                                    //右指针回指   
    if(!T)
        Thrt->lchild = Thrt;                                //二叉树为空,左指针回指
    else
    {
        Thrt->lchild = T;   pre = Thrt;                     //虚设根节点指向头节点
        InThreading(T);
        pre->rchild = Thrt;  pre->RTag = Thread;            //处理最后一个节点指向虚设头结点
        Thrt->rchild = pre;
    }
    return OK;
}

3:中序线索化遍历

中序线索化遍历前驱与后继图
这里写图片描述

核心思想:递归与访问顺序

1:如果你不添加虚设的头结点,也可以利用先序线索化的NULL(G->rchild)作为循环出口
2:这里需要注意如果使用中序线索化就要用中序线索化遍历
这里写图片描述

对应代码
//中序遍历--必须要中序线索化
Status InOrderTraverse(BiThrTree HeadNode, Status(*visit)(TElemType e))
{
    BiThrTree p = HeadNode->lchild;                                 // 虚设头结点指向根节点
    while (p != HeadNode) {                                         //转一圈回来结束
        while (p->LTag == Link) {                                   //一直往左走
            p = p->lchild;
        }
        visit(p->data);                                             //1:访问最左边节点
        while (p->RTag == Thread && p->rchild != HeadNode) {        //右子树为线索,且不为头结点
            p = p->rchild;                                          //2:访问分支节点
            visit(p->data);                                         
        }
        p = p->rchild;                                              //回到分支节点,又开始232行,一个新子树
    }
    return OK;
}
中序线索化及遍历输出结果

这里写图片描述

后序线索化及遍历(我的下篇文章):

https://blog.csdn.net/weixin_39956356/article/details/80144113

二叉树的(先,中,后)序的建树

https://blog.csdn.net/weixin_39956356/article/details/80141837

线索二叉树的基本知识:

https://blog.csdn.net/weixin_39956356/article/details/80141980

猜你喜欢

转载自blog.csdn.net/weixin_39956356/article/details/80142461