左旋后root->right成为新根,因其被上提为父节点,原根变为其左子,且root->right->left被重挂至原根右子以避免丢失;需先保存new_root,再按序重连指针并更新父子关系。

为什么左旋后 root->right 会变成新根?
左旋不是“把右子节点往上拖”,而是重连三根指针:原根、其右子节点、右子节点的左子树。关键在于 root->right 必须非空,否则旋转无意义。旋转后,原 root 变成新根的左孩子,而 root->right->left(即失衡侧的“内支”)被整个挂到原根的右子位置,避免节点丢失。
常见错误是忽略对 root->right->left 的重新赋值,导致子树断裂。实操时务必按顺序操作:
- 先保存
new_root = root->right - 再断开并重连:
root->right = new_root->left - 最后上提:
new_root->left = root - 别忘了更新父子关系(如父指针或返回新根)
rotateRight 中为什么必须检查 root->left 是否存在?
右旋逻辑和左旋对称,但新手常在没判空时直接访问 root->left->right,触发段错误。尤其在递归插入/删除后的平衡调整中,某层节点可能只有单侧子树,此时调用 rotateRight 前若不校验 root->left,程序当场崩溃。
使用场景多见于 AVL 插入后检查平衡因子:当 getBalance(root) == 2 且 getBalance(root->left) == 1,才执行右旋;但前提是 root->left 存在——这个条件不能靠“理论上应该有”来跳过。
立即学习“C++免费学习笔记(深入)”;
AVL 节点旋转后,高度怎么更新才不出错?
旋转本身不改变子树节点数量,但改变了局部拓扑,所以涉及的两个节点(原根和新根)的高度必须重算,且**必须先更新子节点,再更新父节点**。例如左旋后:root 高度依赖其左右子树(其中右子树已变),而 new_root 高度依赖 root(此时 root 尚未更新)。若顺序颠倒,高度值就会滞后一帧,后续平衡判断全错。
推荐写法是封装 updateHeight(Node* n),并在每次旋转结束时显式调用:
updateHeight(root); updateHeight(new_root);
不要试图在旋转过程中“顺手+1”,高度只能由 max(height(left), height(right)) + 1 得出。
为什么单纯旋转无法解决所有失衡?还得配合双旋?
单旋只适用于“外侧插入”情形,比如在 root->left->left 插入导致左偏高。但若插入发生在 root->left->right,此时 root->left 本身右倾,直接对 root 右旋会让 root->left->right 的子树被甩出去——它既不在新根左边,也不在原根右边。
这就是双旋的必要性:先对 root->left 左旋(把插入点“转到外侧”),再对 root 右旋。两步缺一不可,且顺序不能反。漏掉双旋的典型表现是:树看起来旋转了,但 getBalance() 仍返回 ±2,甚至更糟。
容易被忽略的是:双旋后,中间节点(如 root->left)的高度也要更新,而且它现在成了叶子或半叶节点,高度很可能降为 0 或 1——这个细节在调试时极难定位。


















