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

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

普通二叉链表:

  • 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. 中序线索树找前驱后继最简单,先序、后序很复杂


八、优缺点

优点

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

  • 非递归快速遍历

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

缺点

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

  • 树结构改动代价大

相关推荐
shehuiyuelaiyuehao8 小时前
算法56,重排链表
数据结构·算法·链表
suhan10 小时前
【数据结构】七、查找:1.查找的概念、线性结构查找(顺序、折半(二分)、插值、稠密、分块、倒排)
数据结构·算法·排序算法
极客 - L U10 小时前
卡尔曼滤波从零到精通
c语言·数据结构·单片机·嵌入式硬件·mcu
Sarvartha12 小时前
栈的四则运算、栈的递归应用
数据结构·算法
GG.WinGel15 小时前
三元组中心问题
java·数据结构·算法·青少年编程·蓝桥杯
程序员清风15 小时前
缓存、索引与数据结构的工程选择
数据结构·spring·缓存
爱吃火鸡面呀16 小时前
Doris 数据划分实战:List 分区、分桶列与桶数选择
数据结构·list
BK贝壳1 天前
亿级用户签到位图选型复盘:用 bool-hybrid-array 扛冷启动打卡,也把它和 Roaring/Redis 的边界测清楚了
数据结构·python·性能优化·numpy
挖井观天1 天前
《Java数据结构》第一讲:顺序表
数据结构
炘爚1 天前
数据结构算法总结
数据结构·python·算法