线索二叉树的空指针按遍历顺序指向前驱或后继:左空指针指向前驱,右空指针指向后继;具体指向谁取决于线索化所用的遍历方式(如中序、前序、后序),其中中序最常用,因其中序序列天然有序,线索化后可o(1)定位前驱后继并支持双向遍历。

线索二叉树的空指针到底指向谁
线索化不是随便把 nullptr 改成某个节点,而是按遍历顺序“缝合”断点:左空指针指向前驱,右空指针指向后继。关键在于——前驱/后继是谁,取决于你用哪种遍历方式线索化。Inorder 最常用,因为中序结果天然有序,线索化后能 O(1) 找前驱/后继,也方便正向/逆向遍历。
中序线索化的具体步骤和代码要点
线索化本质是一次中序遍历,在访问每个节点时,检查它的左右指针是否为空,并用它们存前驱或后继地址。必须维护一个全局(或递归传入)的 prev 指针,记录上一次真正访问过的节点:
- 当前节点
left为空 → 把它设为线索,指向prev,并标记ltag = 1 - 当前节点
right为空 → 先不处理(后继还没出现),等后续节点访问时,由那个节点的prev(即当前节点)来填它的left线索;但当前节点的right线索要等到它自己变成prev后,被下一个节点设置 - 每次访问完当前节点,执行
prev = current,保证下一轮有正确的前驱
注意:标记字段(如 ltag/rtag)必须是额外布尔值或枚举,不能只靠指针是否为空判断——否则线索指针和真实子树指针无法区分。
线索化后怎么安全地遍历和找前驱/后继
线索化不是终点,用错会段错误。核心规则只有一条:永远先看 tag 标志位,再决定是指针还是线索。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 找中序后继:若
rtag == 1,直接返回right(它就是后继);否则走右子树,再一路left到底(找右子树最左节点) - 找中序前驱:若
ltag == 1,直接返回left;否则走左子树,再一路right到底(找左子树最右节点) - 遍历时别直接
node = node->right——必须判断rtag,否则一碰到线索就跳飞了
典型错误:初始化时没把根节点的 ltag/rtag 设为 0,导致刚进循环就误判线索;或者遍历函数里漏判 tag,当成普通二叉树在走。
为什么不用 std::shared_ptr 或智能指针做线索
线索本质是裸地址引用,而 std::shared_ptr 的控制块开销和线程安全机制会让线索指针变大、变慢,且破坏“一个指针两种语义”的简洁性。更实际的问题是:shared_ptr 的 get() 返回裸指针,但你没法让它的引用计数配合线索生命周期——线索可能指向早已析构的节点,而 shared_ptr 不会自动置空。所以工业级实现一律用原始指针 + 显式 ltag/rtag 字段,手动管理清晰可控。
真正容易被忽略的是:线索化必须在树结构稳定后进行(不能边插入边线索化),而且一旦树发生增删改,所有线索全部失效——得重新线索化。这不是优化技巧,是带约束的数据结构选择。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










