avl树需用有符号height字段、实时计算平衡因子,并在插入/删除后自底向上更新高度并按ll/rr/lr/rl四种情形旋转;split与merge操作中rebalance不可遗漏,否则破坏avl性质。

实现AVL树节点合并与分裂算法,需在插入、删除后精确维护每个节点的平衡因子,并在失衡时通过LL、RR、LR、RL四种旋转恢复高度平衡。不正确更新高度或遗漏某类旋转会导致树持续失衡甚至崩溃。
AVL树节点定义与高度/平衡因子维护
定义节点结构体,包含数据域、左右子指针、【height字段必须为有符号整型,且初始化为1】,不可用无符号类型——否则高度减至0后再减会溢出为极大正数,后续比较全错。
编写get_height函数:空指针返回0;非空则返回node->height。该函数被所有旋转和插入逻辑高频调用,不可内联失效或重复计算。
编写get_balance_factor函数:直接返回get_height(node->left) - get_height(node->right),不缓存、不校验,因平衡因子仅用于判断失衡方向,每次需实时计算。
单旋与双旋的触发条件与实现
当插入导致某节点平衡因子变为2或-2时触发旋转:
方法一:LL型(左左)——当前节点BF=2,且左子节点BF≥0 → 对当前节点执行右旋。
方法二:RR型(右右)——当前节点BF=-2,且右子节点BF≤0 → 对当前节点执行左旋。
方法三:LR型(左右)——当前节点BF=2,但左子节点BF=-1 → 先对左子节点左旋,再对当前节点右旋。
方法四:RL型(右左)——当前节点BF=-2,但右子节点BF=1 → 先对右子节点右旋,再对当前节点左旋。
注意:旋转后必须重新计算涉及节点的高度,顺序是先算子树再算父节点,否则高度值错误会引发下一轮误判。
插入后自底向上回溯更新高度并触发旋转
第一步:递归插入新节点至叶子位置,返回插入后子树的新根。
第二步:在每一层递归返回时,立即更新当前节点height = max(get_height(node->left), get_height(node->right)) + 1。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
第三步:计算当前节点平衡因子,若绝对值≥2,则按前述四种情形调用对应旋转函数,旋转函数返回新子树根,赋值给当前递归层的node指针。
这一步不能省略高度更新——哪怕没旋转也要更新,因为插入可能只影响路径上部分节点的高度;若跳过,后续同路径上更高层的平衡因子计算将全部错误。
分裂操作:从AVL树中分离出键值区间子树
定义split(root, key)函数,返回pair
若root为空,返回{nullptr, nullptr}。
若root->val ≤ key:递归split(root->right, key),将结果中左树接为root->right,右树直接作为整体右树;然后对root执行rebalance(即更新height+检查BF+必要时旋转),最后返回{root, 右树}。
若root->val > key:递归split(root->left, key),将结果中右树接为root->left,左树直接作为整体左树;同样对root rebalance 后返回{左树, root}。
【split过程中任何一次rebalance失败(如旋转后高度未更新)都会使返回子树不再满足AVL性质】
合并操作:将两棵AVL树T1和T2合并,要求T1所有键<T2所有键
取T2的最左节点作为合并后的根候选,将其从T2中摘除(调用delete_min),该节点值必然大于T1最大值、小于T2其余值。
将T1作为新根的左子树,摘下的节点的原右子树作为新根的右子树,构造临时树。
对该临时树根节点执行rebalance——这是唯一一次需要rebalance的位置,其他节点高度均未变。
这一步不可用递归合并:若T1或T2深度差过大,直接拼接会导致新根BF严重超标,必须通过摘中间节点来保证最终高度差≤1。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










