chapter §12 线索二叉树的创建

一、概述

由于给定某一次序的遍历序列,在序列中很容易找到前驱和后继,但在二叉树中寻找指定结点的前驱和后继结点不方便,而且n个结点具有n+1个空链域,因此可以将其利用起来,用来记录该结点的前驱和后继信息。

如果某一结点没有左孩子或右孩子,则将其指针指向其前驱或者后继,称指向前驱和后继结点的指针为线索。这个过程称为二叉树的线索化。
二叉树地线索化是指就是按某种次序遍历一遍二叉树,每遍历到一个结点,对其建立线索。因此就对应有三种线索二叉树。
注: 此处的前驱和后继均是相对于遍历序列(前,中,后序)而言的。

二、原理

在结点中在增加两个标志位,ltag和rtag,如果ltag和rtag为1,则代表相应的左右孩子为线索,如果为0,则表示指向孩子。再设置一个pre指针,用来指向当前结点p的前驱结点,在遍历过程中,如果p的左指针域为空,则将p的左指针指向pre,然后令ltag为1,pre=p;如果pre所指的结点右指针为空,则令其指向p,即指向它的后继(如果存在的话),并让rtag=1。另外需要注意的是对最后一个结点要单独处理,因为它已没有后继结点。

三、代码实现

1、结点定义
typedef int ElemType;
typedef struct ThreadBiTNode {//结点定义
    ElemType data;
    struct ThreadBiTNode *lchild;
    struct ThreadBiTNode *rchild;
    int ltag, rtag;   //左右线索标志,初始值均为0;
} ThreadBiTNode, *ThreadBiTree;
ThreadBiTNode *pre = NULL;//指向结点前驱
2、先序线索二叉树

基于先序遍历,在遍历的途中,为每个结点建立线索。需要注意的是,在先序遍历中,先访问到的是根,如果此时为一个结点建立了左线索,说明该结点无左孩子,应停止遍历左子树,转向遍历右子树,否则会形成环路。

void CreateThreadBiTNode(ThreadBiTNode *P) { //为当前结点建立线索
    if (P == NULL)
        return;
    if (P->lchild == NULL) {//建立前驱线索
        P->lchild = pre; //左孩子指向其前驱
        P->ltag = 1;  //左孩子为线索
    }
    if (pre != NULL && pre->rchild == NULL) {//建立后继线索
        pre->rchild = P;//后继为P
        pre->rtag = 1;//右孩子为线索
    }
    pre = P;//更新前驱
}

void PreThread(ThreadBiTree T) { //先序遍历建立线索
    if (T != NULL) {
    	CreateThreadBiTNode(T);
    	if(T->ltag==0)//存在左孩子 
        	PreThread(T->lchild);
        PreThread(T->rchild);
    }
}

void CreatePreThreadBiTree(ThreadBiTree &T) { //主过程,建立先序线索二叉树
    if (T != NULL) {
        PreThread(T);
        pre->rchild = NULL; //对最后一个点单独处理
        pre->rtag = 1;
    }
}
3、中序线索二叉树

基于中序遍历,在遍历的途中,为每个结点建立线索。

void CreateThreadBiTNode(ThreadBiTNode *P) { //为当前结点建立线索
    if (P == NULL)
        return;
    if (P->lchild == NULL) {//建立前驱线索
        P->lchild = pre; //左孩子指向其前驱
        P->ltag = 1;  //左孩子为线索
    }
    if (pre != NULL && pre->rchild == NULL) {//建立后继线索
        pre->rchild = P;//后继为P
        pre->rtag = 1;//右孩子为线索
    }
    pre = P;//更新前驱
}

void InThread(ThreadBiTree T) { //中序遍历建立线索
    if (T != NULL) {
        InThread(T->lchild);
        CreateThreadBiTNode(T);
        InThread(T->rchild);
    }
}

void CreateInThreadBiTree(ThreadBiTree &T) { //主过程,建立中序线索二叉树
    if (T != NULL) {
        InThread(T);
        pre->rchild = NULL; //对最后一个点单独处理
        pre->rtag = 1;
    }
}
4、后序线索二叉树

基于后序遍历,在遍历的途中,为每个结点建立线索。

void CreateThreadBiTNode(ThreadBiTNode *P) { //为当前结点建立线索
    if (P == NULL)
        return;
    if (P->lchild == NULL) {//建立前驱线索
        P->lchild = pre; //左孩子指向其前驱
        P->ltag = 1;  //左孩子为线索
    }
    if (pre != NULL && pre->rchild == NULL) {//建立后继线索
        pre->rchild = P;//后继为P
        pre->rtag = 1;//右孩子为线索
    }
    pre = P;//更新前驱
}

void PostThread(ThreadBiTree T) { //后序遍历建立线索
    if (T != NULL) {
        PostThread(T->lchild);
        PostThread(T->rchild);
        CreateThreadBiTNode(T);
    }
}

void CreatePostThreadBiTree(ThreadBiTree &T) { //主过程,建立后序线索二叉树
    if (T != NULL) {
        PostThread(T);
        pre->rchild = NULL; //对最后一个点单独处理
        pre->rtag = 1;
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Missヾaurora

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值