AVL树自平衡需显式更新高度、计算平衡因子并执行对应旋转,漏掉任一环节即失衡;插入后必须自底向上更新各节点height并检查bf,bf绝对值>1时按LL/RR/LR/RL四种情形精准旋转,删除后须完整回溯修复。

AVL树的高度自平衡不是靠“自动感知”完成的,而是每次插入/删除后,必须显式计算节点高度差、判断失衡类型、再执行对应旋转——漏掉任一环节,树就不再是AVL。
insert 后必须立即更新 height 并检查平衡因子
很多人在 insert 递归返回后只更新了子树指针,却忘了重新计算当前节点的 height。AVL 的平衡因子定义为 height(left) - height(right),一旦 height 滞后,所有后续判断都会错。
- 每次递归回溯到某节点时,必须立刻执行:
node->height = 1 + max(height(node->left), height(node->right)) - 紧接着计算平衡因子:
int bf = getBalanceFactor(node)(即height(node->left) - height(node->right)) - 平衡因子绝对值 > 1 才需旋转;等于 ±1 是合法过渡态,不触发旋转
- 不要在插入前预判——插入可能发生在深层,只有回溯路径上的节点才需要检查
四种旋转场景对应明确的 BF 组合与子树结构
LL、RR、LR、RL 不是凭感觉命名的,它们由失衡节点及其**较高子节点**的平衡因子符号共同决定。只看根节点 BF 会误判 LR/RL。
- LL:当前节点
bf == 2且左子节点bf >= 0→ 右旋 - RR:当前节点
bf == -2且右子节点bf → 左旋 - LR:当前节点
bf == 2且左子节点bf == -1→ 先对左子节点左旋,再对当前节点右旋 - RL:当前节点
bf == -2且右子节点bf == 1→ 先对右子节点右旋,再对当前节点左旋 - 注意:
bf == 0也属于 LL/RR 场景(例如左子树刚插入叶节点导致其高度+1,但自身左右等高),不能跳过
旋转操作中指针重连顺序不可颠倒
以右旋(LL)为例:rotateRight(node) 不是简单交换左右指针。若先改 node->left,原始 node->left->right 就丢失引用。
- 正确顺序:先保存
node->left(记为newRoot)→ 再将newRoot->right赋给node->left→ 最后把node接到newRoot->right - 旋转后必须重新计算两个受影响节点的
height:node和newRoot(顺序不能反,因为node->height依赖其新子树) - 所有旋转函数返回新的子树根(如
rotateRight返回newRoot),上层必须用该返回值更新父指针
delete 后的平衡修复比 insert 更容易漏检
删除节点后,失衡点可能出现在**向上多层**,而不仅是直接父节点。因为删的是叶或单子节点,高度变化会向上传导,但很多人只检查了一层就停止。
- 必须沿插入/删除路径完整回溯到根,对每个节点都调用
updateHeight()和rebalance() - 即使某层旋转后子树高度未变(例如 RL 旋转后整体高度不变),上层的平衡因子仍可能因子树结构调整而改变,必须继续检查
- 删除时若目标节点有两个子节点,替换后继节点后,要对后继的原位置做删除——这个“二次删除”同样触发完整回溯
最常被忽略的是:旋转后没更新涉及节点的 height,或者在 delete 中只处理了第一处失衡就返回。AVL 的严格性全靠每一步的机械执行,没有“大概平衡”这回事。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











