左旋需更新三个指针:node→right、父节点的left/right、right→left;右旋对称;AVL旋转类型由失衡节点平衡因子及插入方向决定;旋转后须及时准确更新node和新子节点高度。

左旋操作必须更新三个指针:子节点的右子、父节点的左/右、新根的左子
左旋本质是把当前节点 node 的右子 right 提升为新根,node 变成其左子。关键不是“转”,而是指针重连。常见错误是漏掉父节点对 node 的引用更新——如果 node 是某个节点的左子,父节点的 left 要指向 right;如果是右子,则改 right。更隐蔽的坑是忘记更新 right 的左子(原 node 的右子):它要接在 node 的右子位置上。
实操建议:
- 先保存
right = node->right,再断开node->right - 把
node的原右子树(即right->left)挂到node->right - 把
node接到right->left - 最后修正父节点指针:若
node有父节点,判断它是父的left还是right,然后让父对应字段指向right
右旋和左旋是对称操作,但父子关系更新方向相反
右旋是把 node 的左子 left 提为新根,node 成为其右子。逻辑完全镜像:更新 node->left → left->right,再让 left->right = node。最容易错的是混淆左右——比如在右旋里误把 left->left 当作要转移的子树,实际该用 left->right。
实操建议:
- 统一命名习惯:
left和right永远相对于当前旋转节点,不随旋转改变语义 - 写完右旋后,把左旋代码复制一份,机械替换所有
left↔right,再检查父指针更新分支是否也同步翻转 - 若树结构含
parent指针,旋转后node和left/right的parent字段必须同步更新,否则后续高度计算或回溯会出错
AVL 插入后的旋转类型取决于失衡节点与插入路径的相对方向
单旋(LL/RR)和双旋(LR/RL)不是凭空选的,而是由插入位置决定的。例如:在 node 左子的左子插入导致失衡 → LL 型 → 右旋;在 node 左子的右子插入 → LR 型 → 先对左子左旋,再对 node 右旋。很多人直接硬记四种情况,结果在实现中把 balanceFactor 判断写反。
实操建议:
- 只依赖两个信息:失衡节点
node的平衡因子(height(node->left) - height(node->right)),以及插入发生在哪棵子树(递归返回时可传入方向标记) - LL:balance == 2 且插入发生在
node->left的左子树 → 右旋node - LR:balance == 2 且插入发生在
node->left的右子树 → 先左旋node->left,再右旋node - 同理处理 RR / RL,注意 balance == -2 时才进右子分支
手写时高度更新比旋转本身更容易出错
旋转只是指针搬运,真正影响 AVL 正确性的,是旋转后各节点高度是否及时、准确更新。典型错误是只更新了 node 和 right/left 的高度,却忘了它们的子节点(如 right->left)的高度可能已变,而该子节点的高度又会影响上层计算。
实操建议:
- 旋转后,**只重新计算并更新直接受影响的两个节点**:
node和新的子节点(如左旋后是node和right) - 高度计算函数必须安全:空节点返回 -1(不是 0),否则高度差恒为 1,无法触发旋转
- 在插入/删除的递归回溯路径上,每层都调用
updateHeight(),不要试图“省一次”
平衡二叉树的手写难点从来不在旋转动作本身,而在指针更新的完整性和高度维护的时机——少更新一个 parent,或晚算一次 height,整棵树就 quietly 失衡了。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











