线索二叉树

来源:互联网 发布:黄金比例算法 编辑:程序博客网 时间:2024/04/30 14:02
(1)为什么要引入线索二叉树:
当用二叉链表来存储二叉树时,每次只能找到左右孩子的信息,不能直接找到其前驱和后继结点的信息。线索二叉树就解决了这个问题。
(2)线索二叉树的结点结构定义:
结点结构图:
     LChild  Ltag   Data  Rtag   RChild
A.如果有左孩子,则LChild继续指向左孩子,否则,指向该结点的前驱结点。
B.如果有右孩子,则RChild继续指向右孩子,否则,指向该结点的后继结点。
Ltag 用来标记是 左孩子(Ltag = 0)还是 前驱结点 (Ltag = 1)  
Rtag 用来标记是 右孩子(Rtag = 0) 还是 后继结点  (Rtag = 1)
(3)相关基本概念
线索链表:上面的结点结构组成的二叉树的存储结构
线索:在这种存储结构中,指向前驱和后继结点的指针
线索化:对二叉树以某种次序进行遍历并且加上线索的过程
线索二叉树:线索化的二叉树
(4)线索二叉树图
按照上面的思路,有左孩子不做操作,否则,指向其前驱结点。这里要注意,如果没有前驱结点,则指向 null
有右孩子不做操作,否则,指向其后继结点  没有后继结点则指向null

接下来举个例子,如下图的二叉树,


中序遍历的结果为 DGBAECF,线索化为线索二叉树,图如下,画的有些丑,不过就是这个意思。


(5)二叉树的线索化算法
我们知道二叉链表存储的时候会有很多空指针域,线索化就是将二叉链表中的空指针域填上结点的遍历前驱或者后继指针的过程。也就是说,它是在遍历过程中动态修改空指针域的过程。下面利用中序遍历线索化说一下。
基本思想:
A.左孩子指针域为空时,左孩子的位置填入其前驱结点,前驱结点就是刚访问过的最后的结点,所以还要用一个指针 pre记录刚刚被访问的结点,pre的初始值为null,因为第一个遍历的结点没有前驱结点.并将Ltag的值置为 1.
B.右孩子指针域为空时,右孩子的位置填入其后继结点指针。后继结点是在下一次访问时才会知道的,当前并不知道。所以空的右孩子的指针域无法填写,等访问下一个结点时回填。上面我们说过,用pre代表前一个刚访问的结点,所以当前结点就是pre的后继。所以每次回填后继指针即可.并将 Rtag的值置为 1
核心代码:

void InThread(BiTree root){if(root != NULL){InThread(root->LChild);if(root->LChild == NULL){root->LChild = pre;Ltag = 1;}if(pre != NULL && pre->RChild == NULL)      //要记住 后继结点都是 下一次遍历时回填的 慢一步   pre因为初值为null{pre->RChild = root;Rtag = 1;}pre = root;InThread(root->RChild);}}

这是线索二叉树的相关知识,如有不足,还望指教。大笑大笑


1 0
原创粉丝点击