插入新节点必染红,仅可能违反“红节点不能连续”规则;修复时以祖父为单位,根据叔叔颜色与节点位置组合,严格穷举出六种情形,本质是LL/RR/LR/RL四种结构在红黑约束下的颜色+旋转完整覆盖。
红黑树插入后不直接调用或就想平衡?大概率会漏掉祖父节点颜色状态、uncle 节点存在性判断,或误判当前节点在父节点左右子树中的相对位置——这六种情形本质是三种结构模式(LL/RR/LR/RL)在红黑性质约束下的颜色+旋转组合展开,不是独立 case。
为什么插入只产生六种情形,而不是更多?
插入新节点后,红黑树仅违反「红节点不能有红子节点」这一条(新节点染红,父节点若为红则冲突)。修复必须从冲突点向上追溯至祖父节点(grandparent),而 uncle 节点(父节点的兄弟)的颜色决定处理路径:
uncle 为红 → 只需变色:
和
染黑,
染红,再以
为新冲突点继续向上处理
uncle 为黑(或 nullptr)→ 必须旋转:此时需根据
相对于
、
相对于
的左右位置,归类为 LL / RR / LR / RL 四种形态;但 LR 和 RL 各含两种颜色配置(
红/黑),合起来共六种可穷举的情形
所谓“六种”,是
时,对四种旋转形态 × 两种祖父颜色的完整覆盖,不是随意编号。
中如何正确识别当前属于哪一情形?
关键不是数“第几种”,而是分步判断:
立即学习
“
C++免费学习笔记(深入)
”;
C知道
CSDN推出的一款AI技术问答工具
下载
先确认
再获取
,并检查
是否存在(否则已到根,结束)
用
和
组合判断方向,避免硬编码 left/right 字符串匹配
最后查
:若
是
左子,则
;反之亦然。再判
漏掉
的分支,或把
为空当成“黑”来统一处理,会导致 LL/RR 情形被错误归入变色逻辑,后续必崩。
旋转与变色顺序为什么不能颠倒?
所有旋转操作(
/
)都假设子树满足 BST 结构,且旋转后需立即修正三节点颜色,否则中间态必然违反红黑性质:
LL 型(node 是 parent 左、parent 是 grandparent 左):必须先
,再将原
染黑、原
染红 —— 若先变色,
变黑后,其右子(原 grandparent)仍连着一个红子,BST 层级未改但颜色已错
LR 型:必须先
把 node 提到 parent 位,再
,最后统一设色。跳过第一次旋转,直接对 grandparent 右旋,会破坏 BST 中序关系
任何情形下,旋转后若不立刻重设三节点颜色(新 parent 黑,两个子红),都会导致连续红节点或黑高不等
常见错误是把“变色”写成独立函数提前调用,或在旋转后忘记更新
,结果调试时发现树看似平衡了,但
一跑就报「black-height mismatch」。
真正难的不是写出六种 if-else 分支,而是确保每次旋转后,参与旋转的三个节点(new_parent, old_parent, child)颜色重置逻辑与当前路径上
的原始颜色严格对应——这个细节没有注释很容易被忽略,但一旦出错,问题会延迟到后续插入或删除时才暴露。
rotaterecolorparentunclegrandparentgrandparentnodeparentparentgrandparentgrandparentuncle == nullptrinsert_fixupnode != root && node->color == RED && node->parent->color == REDgrandparent = node->parent->parentgrandparentnode == node->parent->leftnode->parent == grandparent->leftuncleparentgrandparentuncle = grandparent->rightuncle && uncle->color == REDuncle == nullptruncleleft_rotateright_rotateright_rotate(grandparent)parentgrandparentparentleft_rotate(parent)right_rotate(grandparent)node->parent->colorverify_rbtree()grandparent