线索二叉树的讨论

线索二叉树

  1. 前面谈到了遍历二叉树,遍历二叉树是以一定规则(先序,中序或后序)将二叉树中的结点排列成一个线性序列。这实际上是对非线性化结构进行线性化操作,使每个结点(除第一个和最后一个外)在这些序列中有且仅有一个前驱或后继。

  2. 但当以二叉链表作为存储结构时,只能找到结点左右孩子的信息,并不能得到结点的前驱和后继信息。一种比较简单的方法当然是在每个结点结构中再加入两个指针域,前驱指针域保存其前驱信息,后继指针域保存其后继信息。但这样降低了存储密度,并不合适。

  3. 还有一种方法是利用二叉链表的一个重要特性:在n个结点的二叉链表中一定含有n+1个空链域。我们可以利用这n+1个空链域来保存前驱和后继。 而非叶子结点我们可以根据遍历特点来找其前驱或后继。

  4. 如作出如下规定:若结点有左子树,则其lchild域指示其左孩子,否则另lchild域指向其前驱;同理若结点有右子树,则其rchild域指示其右孩子,否则另rchild域指向其后继。当然我们需要再加入两个标志位LTag和RTag来区分是指向孩子还是前后,结点结构如下:

    lchild LTag data RTag rchild

    LTag=0 (lchild域指向结点的左孩子)
    LTag=1 (lchild域指向结点的前驱)
    RTag=0 (rchild域指向结点的右孩子)
    RTag=1 (rchild域指向结点的后继)

  5. 以上面这种结点结构构成的二叉链表作为二叉树的存储结构,叫做线索链表。其中指向前驱和后继的指针称为线索,所对应的二叉树称为线索二叉树

  6. 下图为一个中序二叉树和它的中序线索链表,其中实线为指针(指向左右子树),虚线为线索(指向前驱和后继)。对二叉树以某种次序遍历使其变为线索二叉树的过程叫做线索化

  7. 我们如果要遍历线索二叉树,则需要找到序列中的第一个结点,然后依次找结点的后继,直到后继为空时而止。如何找到结点的后继我们需要在这里讨论。

  8. 观察上图,叶子结点的rchild域是直接指向其后继的,而非叶子结点的后继,根据中序遍历(左根右)的规律再结合上图可以得出非叶子结点的后继是其右子树中序遍历的第一个结点,即右子树中最左下的结点。 反之,在中序线索树种找结点前驱的规律是:若其左标志为1,则lchild域指向其前驱,否则其左子树中序遍历的最后一个结点为其前驱,即左子树最右下的结点。

  9. 同理,也可找出后序或先序线索二叉树结点的后继,如下图是后序线索二叉树找后继结点,也很好理解。

  10. 故当所用二叉树需要经常遍历或查找结点的前驱和后继时,适合采用线索链表作存储结构。

  11. 有时为了方便起见,仿照线性表的存储结构,在二叉树的线索链表上也添加一个头结点,并令其lchild域指向二叉树的根结点,其rchild域指向中序遍历时访问的最后一个结点(之所以这样链接,因为头结点沟通了头尾,设根结点为其左孩子,则它的rchild域需要链接尾结点);反之,令二叉树中序序列的第一个结点的lchild域指针和最后一个结点rchild域的指针均指向头结点(序列的第一个结点的前驱和最后一个结点的后继即为头结点)。这好比为二叉树建立了一个双向线索链表,既可以从第一个结点起顺后继进行遍历,也可以从最后一个结点起顺前驱进行遍历。

发布了77 篇原创文章 · 获赞 19 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_42932834/article/details/93891513
今日推荐