You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AVL树实现异常:中序遍历无法打印全部节点,附插入代码

排查AVL树插入后中序遍历无法打印所有节点的问题

嘿,我看你在AVL树插入操作后遇到中序遍历漏节点的问题了,结合你给出的代码片段,咱们来梳理几个最可能的原因和解决办法:

1. 核心问题:缺失插入后的平衡调整逻辑

AVL树的核心是插入后必须维护树的平衡,你的代码片段在递归插入左子树后就截断了——没有更新节点高度、检查平衡因子,也没有做旋转操作。如果跳过这一步,插入操作会导致树结构失衡,节点的左右指针或父指针指向错误,直接导致中序遍历无法遍历到所有节点。

你需要在递归插入左右子树后,补充以下步骤:

  • 更新当前节点的高度
  • 计算平衡因子(左子树高度 - 右子树高度)
  • 根据平衡因子判断是否失衡,执行对应的旋转(LL/LR/RR/RL)

给你补全这部分的示例代码:

// 辅助函数:获取节点高度,空节点返回0
int getHeight(avl_node* t) {
    return t == NULL ? 0 : t->height;
}

// 辅助函数:计算平衡因子
int getBalance(avl_node* t) {
    return t == NULL ? 0 : getHeight(t->left) - getHeight(t->right);
}

// 右旋转函数
void rightRotate(avl_node* &t) {
    avl_node* leftChild = t->left;
    avl_node* leftRightChild = leftChild->right;

    // 执行旋转
    leftChild->right = t;
    t->left = leftRightChild;

    // 更新高度
    t->height = max(getHeight(t->left), getHeight(t->right)) + 1;
    leftChild->height = max(getHeight(leftChild->left), getHeight(leftChild->right)) + 1;

    // 更新根节点指针
    t = leftChild;
}

// 左旋转函数
void leftRotate(avl_node* &t) {
    avl_node* rightChild = t->right;
    avl_node* rightLeftChild = rightChild->left;

    // 执行旋转
    rightChild->left = t;
    t->right = rightLeftChild;

    // 更新高度
    t->height = max(getHeight(t->left), getHeight(t->right)) + 1;
    rightChild->height = max(getHeight(rightChild->left), getHeight(rightChild->right)) + 1;

    // 更新根节点指针
    t = rightChild;
}

// 补全后的插入函数
void AVL_Tree::insert(const Tree & x, avl_node* & t){
    if(t == NULL){
        // 注意:叶子节点高度建议设为1,和getHeight的空节点返回0逻辑统一
        avl_node* p = new avl_node(x, NULL, NULL, 1);
        t = p;
        ++size;
        cout << "added new node success" << endl;
    } 
    else if(x < t->element){
        cout << " x < t element" << endl;
        insert(x, t->left);
        
        // 插入左子树后,维护平衡
        t->height = max(getHeight(t->left), getHeight(t->right)) + 1;
        int balance = getBalance(t);

        // LL型失衡
        if(balance > 1 && x < t->left->element){
            rightRotate(t);
        }
        // LR型失衡
        if(balance > 1 && x > t->left->element){
            leftRotate(t->left);
            rightRotate(t);
        }
    }
    else if(x > t->element){
        cout << " x > t element" << endl;
        insert(x, t->right);
        
        // 插入右子树后,维护平衡
        t->height = max(getHeight(t->left), getHeight(t->right)) + 1;
        int balance = getBalance(t);

        // RR型失衡
        if(balance < -1 && x > t->right->element){
            leftRotate(t);
        }
        // RL型失衡
        if(balance < -1 && x < t->right->element){
            rightRotate(t->right);
            leftRotate(t);
        }
    }
    else{
        // 重复元素,根据需求处理,比如不插入
        cout << "element already exists" << endl;
    }
}

2. 检查中序遍历的实现是否正确

除了插入的问题,也有可能是中序遍历本身写错了。正确的中序遍历逻辑应该是:

void AVL_Tree::inorderTraversal(avl_node* t){
    if(t == NULL){
        return;
    }
    // 先递归左子树
    inorderTraversal(t->left);
    // 访问当前节点
    cout << t->element << " ";
    // 再递归右子树
    inorderTraversal(t->right);
}

如果你的遍历函数漏掉了递归右子树,或者终止条件错误,也会导致打印不全。

3. 节点高度的一致性问题

注意你新建节点时的高度设置,要和getHeight函数的逻辑统一。比如如果getHeight对空节点返回0,那叶子节点的高度应该设为1,这样父节点的高度计算才会正确——否则平衡因子的计算会出错,旋转逻辑不触发,最终导致树结构损坏。

内容的提问来源于stack exchange,提问作者Michelle

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 04:06:30