双红冲突修复本质是局部子树结构归一化,须按“先查uncle颜色→再判方向”的严格顺序执行变色或旋转,否则会漏修、引入新冲突或导致指针错乱。

双红冲突修复不能只靠记忆旋转口诀——它本质是局部子树的结构归一化过程,变色和旋转必须按严格顺序触发,否则会漏修或引入新冲突。
什么是双红冲突?它为什么必须立刻修复
双红冲突指父节点 parent 和其子节点 node 同时为红色,违反红黑树性质 4(任意路径上不能有两个连续红节点)。注意:它不等于“插入后出现两个红节点”,而是特指父子关系中的红-红相邻;祖父节点 grandparent 必须存在且为黑色(否则递归向上已出问题),叔节点 uncle 的颜色决定后续分支。
- 如果
uncle是红色:只需变色(parent、uncle黑,grandparent红),然后以grandparent为新node继续向上检查 - 如果
uncle是黑色(或为nullptr):必须旋转,此时node相对于parent的位置(左/右)与parent相对于grandparent的位置共同决定用单旋还是双旋
四种旋转场景怎么判断?关键看父子-爷孙方向组合
不要背“LL/RR/LR/RL”,直接查 node == parent->left 和 parent == grandparent->left 两个布尔值。只有当两者同向(都为 true 或都为 false)时才用单旋;异向时必须先对 node 和 parent 单旋,再对新父节点和 grandparent 单旋。
-
node是parent的左子,parent是grandparent的左子 → 对grandparent右旋 -
node是parent的右子,parent是grandparent的右子 → 对grandparent左旋 -
node是parent的左子,parent是grandparent的右子 → 先对parent右旋,再对grandparent左旋 -
node是parent的右子,parent是grandparent的左子 → 先对parent左旋,再对grandparent右旋
旋转后,原 parent 成为新子树根,必须将其染黑;原 grandparent 染红(保持黑高不变);新根的两个子节点(若有)颜色不变。
立即学习“C++免费学习笔记(深入)”;
变色和旋转的执行顺序不能颠倒
修复函数入口处必须先检查 uncle 颜色,而不是先判断方向。因为变色分支(uncle 红)不需要旋转,且处理完后要递归向上;而旋转分支(uncle 黑)处理完就终止(旋转+染色后子树黑高恢复,不再影响上层)。若顺序错乱,比如在 uncle 红时误入旋转逻辑,会导致指针错乱或重复染色。
- 伪代码关键结构必须是:
if (uncle && uncle->color == RED)→ 变色 + 递归调用fixDoubleRed(grandparent) - 否则 → 判断方向 → 执行对应旋转 → 染色(
parent->color = BLACK,grandparent->color = RED) - 所有旋转函数内部必须更新父指针(例如左旋后,
newRoot->parent = oldRoot->parent),否则后续grandparent查找失效
容易被忽略的边界细节
实际写代码时,grandparent 可能是根节点,此时旋转后需手动重置 root 指针并强制染黑(根必须为黑);uncle 为 nullptr 视为黑色,但访问其 color 前必须判空,否则段错误;插入新节点初始设为红色,但它的左右子指针必须初始化为 nullptr,否则旋转中空指针解引用。
- 检查
uncle颜色前:先写Node* uncle = (parent == grandparent->left) ? grandparent->right : grandparent->left;,再if (uncle && uncle->color == RED) - 旋转后若
grandparent成为叶子,它的子指针可能非空但未参与旋转逻辑——这些子树黑高未变,无需额外操作 - 调试时打印每步的
node、parent、grandparent地址和颜色,比单步跟指针更高效
真正卡住的往往不是算法逻辑,而是某个旋转后忘记更新某条父链指针,或者 nullptr 没判就取 ->color。


















