二叉树的遍历和线索二叉树--中序线索二叉树的构造

一、为什么要用线索二叉树

普通二叉链表:

  • n 个结点,一共2n 个指针域

  • 真正指向孩子的指针只有 n-1 个

  • 剩余 n+1 个空指针,空间浪费

解决办法:

利用空左、空右指针,存放中序遍历的前驱、后继结点

加上标记位区分,就是中序线索二叉树


二、线索结点结构

复制代码
数据 data
左指针 lchild  + 左标记 ltag
右指针 rchild  + 右标记 rtag
  • `ltag = 0`:lchild 指向左孩子

  • `ltag = 1`:lchild 是前驱线索

  • `rtag = 0`:rchild 指向右孩子

  • `rtag = 1`:rchild 是后继线索


三、构造核心规则(中序:左→根→右)

  1. 按照中序遍历顺序递归遍历整棵树

  2. 定义全局指针 `pre`,永远记录上一个访问过的结点

  3. 当前结点左孩子为空

→ 左指针指向 `pre`,`ltag=1`

  1. 前驱结点 `pre` 右孩子为空

→ pre 右指针指向当前结点,`pre.rtag=1`

  1. 遍历完当前结点,更新 `pre = 当前结点`

四、一步步构造流程(画图逻辑)

  1. 初始化 `pre = null`

  2. 递归线索化左子树

  3. 处理当前根结点:绑定前驱线索

  4. 绑定前驱结点到当前结点的后继线索

  5. 更新前驱 pre

  6. 递归线索化右子树


五、Java 标准构造代码

1.线索结点类

复制代码
class InThreadNode {
    int data;
    InThreadNode left;
    InThreadNode right;
    int ltag;   //0=左孩子  1=前驱线索
    int rtag;   //0=右孩子  1=后继线索

    public InThreadNode(int data) {
        this.data = data;
        left = null;
        right = null;
        ltag = 0;
        rtag = 0;
    }
}

2.中序线索化核心递归代码

复制代码
public class ThreadTree {
    static InThreadNode pre = null; //记录前驱结点

    //中序遍历实现二叉树线索化
    public void createInThread(InThreadNode root) {
        if (root == null) return;

        //1.递归线索化左子树
        createInThread(root.left);

        //2.处理当前结点:左空 → 指向前驱
        if (root.left == null) {
            root.left = pre;
            root.ltag = 1;
        }

        //3.处理前驱结点:右空 → 指向当前结点(后继)
        if (pre != null && pre.right == null) {
            pre.right = root;
            pre.rtag = 1;
        }

        //前驱后移
        pre = root;

        //4.递归线索化右子树
        createInThread(root.right);
    }
}

六、中序线索二叉树遍历(不用栈、不用递归)

复制代码
//线索树遍历
public void threadTraverse(InThreadNode root){
    InThreadNode p = root;

    //找到中序第一个结点(最左下)
    while(p != null && p.ltag == 0){
        p = p.left;
    }

    while(p != null){
        System.out.print(p.data + " ");

        //右是线索,直接走后继
        if(p.rtag == 1){
            p = p.right;
        }
        //右是孩子,找右子树最左下结点
        else{
            p = p.right;
            while(p != null && p.ltag == 0){
                p = p.left;
            }
        }
    }
}

七、考点

  1. 线索化本质 = 一次完整中序遍历

  2. `pre` 是连接前驱后继的关键

  3. 叶子结点:左右指针全部是线索

  4. 线索二叉树:无需递归、无需栈即可遍历

  5. n 个结点二叉链表,固定空指针数量:n+1 个

  6. 中序线索树找前驱后继最简单,先序、后序很复杂


八、优缺点

优点

  • 充分利用空闲指针,不额外占用空间

  • 非递归快速遍历

  • 快速查询结点遍历前驱、后继

缺点

  • 插入、删除结点麻烦,需要重新修改所有线索

  • 树结构改动代价大

相关推荐
Darling噜啦啦4 天前
列表转树算法深度解析:从 Map 到 Reduce 的两种实现,面试高频考点
数据结构·算法·面试
小小工匠5 天前
Redis - 事务机制:能实现 ACID 属性吗
数据结构·redis·性能优化·并发·持久化
玖玥拾5 天前
C/C++ 数据结构(七)栈、容器适配器
c语言·数据结构·c++··容器适配器
Qres8215 天前
算法复键——树状数组
数据结构·算法
牛油果子哥q5 天前
并查集(DSU)超精讲,路径压缩、按秩合并、万能模板、连通性判定、最小生成树与刷题实战全解
数据结构·c++·最小生成树·并查集
凌波粒5 天前
LeetCode--491.递增子序列(回溯算法)
数据结构·算法·leetcode
WL学习笔记6 天前
单项不带头不循环链表
数据结构·链表
小糯米6016 天前
JS 数组
数据结构·算法·排序算法
小欣加油6 天前
leetcode3612 用特殊操作处理字符串I
数据结构·c++·算法·leetcode·职场和发展
凌波粒6 天前
LeetCode--90.子集II(回溯算法)
数据结构·算法·leetcode