c++中如何实现AVL树_c++平衡二叉树插入与旋转方法

AVL树插入后必须自底向上检查并旋转,因插入可能使某节点平衡因子变为±2;首次发现失衡节点即旋转修复,再向上递归检查。LL、RR、LR、RL四种旋转由插入路径方向决定,旋转需更新涉及节点高度并返回新根。

AVL树插入后为什么必须检查并可能旋转

因为AVL树要求任意节点的左右子树高度差(平衡因子)绝对值 ≤ 1。单纯插入可能导致某节点平衡因子变为 ±2,此时必须通过旋转恢复平衡。关键不是“插完再统一调整”,而是从插入点向上回溯到根,**首次发现失衡节点就立即旋转修复**,之后其父节点高度变化可能引发更高层失衡,需继续向上检查。

四种旋转场景怎么判断和选择

失衡节点记为 node,插入发生在它的子树中。旋转类型由插入路径的“方向组合”决定:

  • LL:插入发生在 node->left->left —— 右旋 node
  • RR:插入发生在 node->right->right —— 左旋 node
  • LR:插入发生在 node->left->right —— 先对 node->left 左旋,再对 node 右旋
  • RL:插入发生在 node->right->left —— 先对 node->right 右旋,再对 node 左旋

实际编码中,通常用平衡因子(height(node->right) - height(node->left))和插入后子树高度变化方向联合判断,避免重复遍历。

旋转操作本身要改哪些指针

旋转本质是局部子树重构,只修改涉及的 3–4 个节点的 left/right 指针,不改变键值。以右旋为例(LL):

立即学习“C++免费学习笔记(深入)”;

Node* rotateRight(Node* y) {
    Node* x = y->left;
    Node* T2 = x->right;
x->right = y;
y->left = T2;

// 更新高度(假设 height() 是成员函数或辅助函数)
y->height = max(height(y->left), height(y->right)) + 1;
x->height = max(height(x->left), height(x->right)) + 1;

return x;

}

注意:T2 非空时,它原属于 x 的右子树,旋转后成为 y 的左子树;所有旋转都必须更新参与节点的高度,否则后续平衡因子计算错误。

插入函数里如何嵌入平衡维护逻辑

标准递归插入返回新子树根,每层返回前检查当前节点是否失衡,并执行对应旋转。典型结构如下:

Node* insert(Node* node, int key) {
    // 1. 标准BST插入
    if (!node) return new Node(key

); if (key < node->key) node->left = insert(node->left, key); else if (key > node->key) node->right = insert(node->right, key); else return node; // 重复键,不插入
// 2. 更新当前节点高度
node->height = 1 + max(height(node->left), height(node->right));

// 3. 计算平衡因子
int bf = getBalanceFactor(node);

// 4. 四种失衡情况处理(返回旋转后的新根)
if (bf > 1 && key < node->left->key)     // LL
    return rotateRight(node);
if (bf < -1 && key > node->right->key)   // RR
    return rotateLeft(node);
if (bf > 1 && key > node->left->key)     // LR
    return rotateLeftRight(node);
if (bf < -1 && key < node->right->key)   // RL
    return rotateRightLeft(node);

return node; // 无需旋转,返回原节点

}

容易忽略的点:旋转后必须返回新根(如 rotateRight 返回 x),否则父节点的指针会指向被“转下去”的旧根,导致树断裂;另外,getBalanceFactor 必须用 height(right) - height(left),符号反了会导致 LL/RR 判断颠倒。