zoukankan      html  css  js  c++  java
  • 线索二叉树

    ---

    What is it?

    image-20210515155246407

    Attempt_1

    要找到指定节点p在中序遍历序列中的前驱:

    再次遍历,设置两个工作指针pre和q分别指向前一个访问的结点和当前访问的结点

    直到q指向指定结点p,此时pre即为前驱

    Attempt_2

    image-20210515155748221

    n个结点的二叉树拥有(n+1)个空链域,利用这些空链域来提供线索,即形成了线索二叉树

    存储结构

    image-20210515160252951

    显然,只有具有空链域的结点可以在 O(1) 时间内根据线索找到结果

    三种线索二叉树

    image-20210515161124228

    线索化

    中序线索化

    image-20210515162506761

    实际上在中序遍历中上图绿框的检查是不必要的,因为中序遍历下最后一个结点的右孩子必定为空,所以处理到最后一个结点时可以直接将 rtag置为1

    按照类似的思路,我们来看看先序线索化:

    先序线索化

    image-20210515163949477

    注意!!!:在构建前后继关系时,能依靠的只有两个工作指针 preq,即只能通过这两个指针来确定已知的前后继关系(pre是 q的前继,q是 pre的后继)

    因此,需要关注线索的读写顺序,例如在先序遍历中,由于 visit 发生在递归左子树之前,如果 visit 将本来为null的q的左孩子修改为了指向pre的线索,就会形成死循环

    为何只会在先序遍历中出现上述“转圈现象”呢?从下面的访问次序就可以看出

    中序:左 根

    后序:

    先序:根 左 右 只有在先序中对根的操作先于左孩子,相当于发生了读后写冲突(本来期望在读到左孩子为null后再对根线索化)

    解决方法如下:在递归线索化左子树之前先判断左孩子是否已经是线索( ltag == 0 ?):

    image-20210515165428209

    后序线索化

    image-20210515170425732

    这里就要注意对最后一个结点的处理,因为后序遍历下最后访问的结点是可能有右孩子

    小结

    image-20210515170804095

    === 后序注意尾结点判断,先序注意死循环 ===

  • 相关阅读:
    Linux如何同步时间/更新时间
    Linux关机/重启/及注销命令
    Linux如何查看别名和取消别名
    Linux查看历史记录
    Linux命令行快捷键有哪些
    win10产品密钥 win10永久激活密钥(可激活win10所有版本 )
    Xshell如何连接
    Xshell6 优化
    逻辑运算符
    可变类型与不可变类型
  • 原文地址:https://www.cnblogs.com/potofsalt/p/14826469.html
Copyright © 2011-2022 走看看