avl树旋转前必须更新节点高度,否则getbalancefactor()返回错误值导致平衡判断失效;每次插入或删除后需从修改点向上回溯更新各层高度,漏更新将使整个平衡逻辑崩溃。

AVL树旋转前必须更新高度
不更新节点高度,旋转后 getBalanceFactor() 会返回错误值,导致后续判断失灵——这是新手最常卡住的地方。高度不是装饰字段,是所有平衡判断的依据。
每次插入或删除后,从修改点向上回溯到根,逐个调用 updateHeight()(通常就是 node->height = 1 + max(getHeight(node->left), getHeight(node->right)))。漏掉某一层,整个平衡逻辑就崩了。
常见错误现象:rotateLeft() 执行完,左子树高度反而比右子树高 2,说明旋转前父节点高度没更新,或旋转后没重算新根高度。
右旋(RR)和左旋(LL)的触发条件与代码边界
RR 旋转发生在:当前节点 balanceFactor > 1(左重),且其左子节点的 balanceFactor >= 0(左子节点不右重)。LL 同理,但方向相反。
注意那个 >= 0:当左子节点 balanceFactor == 0 时,仍应走 RR,不是 RL。很多实现错写成 > 0,导致插入序列如 [10, 5, 15, 3] 后无法正确平衡。
实操建议:
- 写
getBalanceFactor(node)时,空指针返回 0,避免分支里反复判空 -
rotateRight(node)中,新根是node->left,原node->left->right变成新根的右子树,别忘了把原node接到新根右子树的“左挂点”上 - 旋转后必须立即调用
updateHeight()更新node和新根的高度,顺序不能反
LR 和 RL 双旋转的本质是两次单旋
LR 不是特殊操作,就是先对左子节点做 rotateLeft(),再对当前节点做 rotateRight();RL 则是先 rotateRight() 再 rotateLeft()。强行写一个“双旋函数”反而增加理解负担和出错概率。
关键点在于:第一次旋转后,必须更新被旋转子树的根高度,否则第二次旋转时 getBalanceFactor() 仍用旧值,可能跳过本该做的第二次旋转。
典型陷阱:在 insert() 递归返回途中判断 balanceFactor,发现需要 LR,于是直接 node->left = rotateLeft(node->left),但忘了此时 node->left 已变,必须紧接着 node = rotateRight(node),且两次旋转后都要调 updateHeight()。
insert() 递归返回时才做平衡,别在递归中途提前旋转
AVL 的平衡操作必须在插入完成、递归栈开始回退时进行。如果在向下找插入位置过程中就旋转,会破坏 BST 性质(比如把大于当前值的节点转到左边)。
标准结构是:
Node* insert(Node* node, int key) {
if (!node) return new Node(key);
if (key key) node->left = insert(node->left, key);
else if (key > node->key) node->right = insert(node->right, key);
else return node; // duplicate
<pre class="brush:php;toolbar:false;">updateHeight(node); // ← 回溯第一步:更新当前层高度
int bf = getBalanceFactor(node);
if (bf > 1 && key left->key) return rotateRight(node); // LL
if (bf node->right->key) return rotateLeft(node); // RR
if (bf > 1 && key > node->left->key) { // LR
node->left = rotateLeft(node->left);
return rotateRight(node);
}
if (bf right->key) { // RL
node->right = rotateRight(node->right);
return rotateLeft(node);
}
return node;}
最后一句 return node 很关键:不是所有路径都旋转,没触发条件就原样返回,靠上层继续处理。漏掉这个,树就断了。
真正容易被忽略的是:updateHeight() 必须放在所有旋转判断之前,且必须对每个回溯节点都执行——哪怕它最终没被旋转,它的子树高度可能已变,影响上层 balanceFactor 计算。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











