【学习笔记----数据结构11-线索二叉树】

线索二叉树

线索二叉树的原理

我们把指向前驱和后继的指针称为线索,加上线索的二叉链表称为线索,加上线索的二叉链表为线索链表,相应的二叉树就称为线索二叉树(Threaded  Binary  Tree)

lchild

ltag

data

rtag

rchild

 

其中:

l  ltag为0时指向该结点的左孩子,为1时指向该结点的前驱

l  rtag为0时指向该结点的右孩子,为1时指向该结点的后继

 

实现代码如下:

typedef  enum{Link,Thread}   PointerTag;

typedef  struct  BiThrNode

{

      TElemType   data;

      struct   BiThrNode    *lchild,*rchild;

       PointerTag   LTag;

       PointerTag   RTage;

}

线索化的实质就是将二叉链表中的空指针改为指向前驱或后继的线索。由于前驱和后继信息只有在遍历该二叉树时才能得到,所以线索化的过程就是在遍历的过程中修改空指针的过程

/*中序遍历进行中序线索化*/

 

BiThrTree   pre; //全局变量,始终指向刚刚访问过的结点

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; //保持pre指向p的前驱

          InThreading(p->rchild);  //递归右子树线索化

}

}

除红色部分和二叉公示的中序遍历递归代码几乎完全一样。只不过将本是打印的结点的功能改成线索化的功能。

中间加粗的代码做了这样一些事情if(!p->lchild)表示如果某结点的左指针域为空,因为其前驱结点刚刚访问过,赋值给了pre,所以可以将pre赋值给p->lchild,并修改p-Ltag=Thread(也就是定义为1)完成前驱结点的线索化。

后继就是要稍稍麻烦一些。因为此时p结点的后继还没有访问,因此只能对它前驱结点pre的右指针rchild做判断,if(!pre->rchild)表示如果为空,并且设置pre->RTag=Thread,完成后继结点的线索化。完成前驱和后继的判断后,别忘记将当前的结点p赋值给pre,以便于下一次使用。

有了线索二叉树后,我们对它的进行遍历时发现,其实就等于是操作一个双向链表结构。

和双向链表结构一样,在二叉树线索链表上添加一个头结点,并令其lchild域的指针指向二叉树的根结点,其rchild域指针指向之前中序遍历时访问的最后一个结点。反之,令二叉树的中序遍历中的第一个结点中,lchild域指针和最后一个结点的rchild域均指向头结点。这样定义的好处就是我们既可以从第一个结点起顺序后继进行遍历,也可以从最后一个结点起顺序前驱进行遍历。


遍历代码如下:

T指向头结点,头结点左链lchild指向根结点,头结点右键rchild指向中高序遍历的最后一个结点,中序遍历二叉线索链表表示的二叉树T

Status  InOrderTraverse_Thr(SiThrTree  T)

{

     BiThrTree  p;

     p = T->lchild;

     while(p!=T)

      {

         while(p->LTag==Link)

                   p=p->lchild;

         printf(“%C”,p->data);

         while(p->RTag==Thread &&p->rchild!=T)

          {

               p=p->rchild;

                printf(“%C”,p->data);

          }

                p=p->rchild;

      }

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值