左旋必须更新父节点指针,否则树结构断裂;核心是右子节点升为新根、原节点变其左孩子,并同步更新双向父指针、子指针及树根指针。

左旋操作必须更新父节点指针,否则树结构断裂
左旋本质是把 node 的右子节点 right 提升为新子树根,node 变为其左孩子。但常见错误是只改了 node 和 right 的子指针,却忘了更新 right 的父指针、以及原 node 父节点的对应子指针。
实操要点:
- 先保存
right的左子树(即right->left),它将成为node的新右子树 - 设置
right->left = node,再设node->parent = right—— 这步漏掉会导致node父指针仍指向旧父,后续遍历或删除会跳错 - 若
node原来是其父节点的左/右孩子,必须通过node->parent->left或node->parent->right把指针重定向到right;若node是整棵树的根,则需同步更新树的root指针 - 最后别忘更新
node和right的color字段(红黑树中旋转不改变颜色,但逻辑上要保持语义清晰)
右旋时要注意空指针解引用,尤其在插入修复早期阶段
右旋是对称操作,但实际编码中最容易在 node->left == nullptr 时直接调用 rotate_right(node),导致访问 node->left->right 崩溃。红黑树插入后调用右旋前,必须确保 node->left 非空——这不是冗余检查,而是协议前提。
典型场景:
- 插入新节点后触发
case 1(叔节点为红色),仅变色不旋转;进入case 2或case 3才可能右旋 -
case 2中当前节点是父节点的右孩子,需先对其父节点左旋,再对祖父右旋 —— 这里两次旋转的入参必须严格非空 - 建议封装成带断言的版本:
assert(node != nullptr && node->left != nullptr);
rotate_left 和 rotate_right 函数不应修改节点颜色,但要重置 parent 指针链
旋转本身不违反红黑树五条性质,所以标准实现中这两个函数完全不碰 color。真正影响颜色的是后续的 recolor 步骤(如插入修复中的变色)。但很多人误以为“旋转后要翻转颜色”,这是混淆了 AVL 的平衡因子调整和红黑树的双色约束。
关键细节:
-
rotate_left(Node* node)返回值应为新的子树根(即原node->right),方便上层直接赋值,比如parent->right = rotate_left(node); - 所有涉及
parent的指针更新必须双向:既要child->parent = parent,也要在parent的子指针字段中写入child,否则会出现悬挂指针 - 如果使用智能指针(如
std::unique_ptr),旋转需额外处理所有权转移,此时建议先用裸指针实现逻辑,再迁移
调试旋转逻辑时,优先打印父子关系而非整棵树
红黑树节点少时肉眼可验,但一旦插入十几节点,靠 print_tree() 很难定位哪一步旋错了。更高效的方式是每次旋转前后,用一行日志输出关键三元组:[node->val, node->parent->val, node->parent->left == node ? "L" : "R"]。
这样能快速发现:
- 旋转后
node->parent没更新 → 日志显示父值仍是旧值 - 父节点的子指针未重连 → 日志中父节点仍指向旧
node,但node的父却已变成别人 - 根节点旋转后未更新
root→ 日志首行父值为 0 或非法地址
比起堆栈跟踪或内存快照,这种轻量级打点在红黑树调试中几乎总是最快定位手段。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











