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

如何实现每个ID节点指向子AVL树的AVL树结构?

解决两层AVL树的实现问题

看起来你已经搭好了AVL树的基础框架,现在要实现的是以ID为上层AVL节点,每个ID节点关联一棵存储对应element的AVL树,核心是调整结构体定义和插入逻辑,让两层树能正确关联起来。我来一步步帮你梳理清楚:

1. 重构结构体定义

你原来的avl_node_id结构设计有点绕,我们直接给它加一个指向element层AVL树根节点的指针,逻辑会更清晰:

class AVLTree {
public:
    AVLTree();
    void readFile();
    void printToScreen();

    // 存储element的AVL节点结构
    struct avl_node {
        int data;
        struct avl_node *left;
        struct avl_node *right;
    };

    // 存储ID的AVL节点,每个节点绑定一棵element的AVL树
    struct avl_node_id {
        int id;                  // 存储ID数据
        avl_node* elem_root;     // 指向对应element树的根节点
        struct avl_node_id *left;
        struct avl_node_id *right;
    }*id_root;

    // 针对element树的AVL工具方法
    int height(avl_node *);
    int diff(avl_node *);
    avl_node *rr_rotation(avl_node *);
    avl_node *ll_rotation(avl_node *);
    avl_node *lr_rotation(avl_node *);
    avl_node *rl_rotation(avl_node *);
    avl_node* balance(avl_node *);
    avl_node* insert_element(avl_node *, int);  // 插入element的方法

    // 针对ID树的AVL工具方法(结构不同,需单独实现)
    int height_id(avl_node_id *);
    int diff_id(avl_node_id *);
    avl_node_id *rr_rotation_id(avl_node_id *);
    avl_node_id *ll_rotation_id(avl_node_id *);
    avl_node_id *lr_rotation_id(avl_node_id *);
    avl_node_id *rl_rotation_id(avl_node_id *);
    avl_node_id* balance_id(avl_node_id *);
    avl_node_id* insert_id(avl_node_id *, int, int);  // 插入ID+对应element

    // 遍历与打印方法
    void display_element(avl_node *, int);
    void display_id(avl_node_id *, int);
    void inorder_element(avl_node *);
    void inorder_id(avl_node_id *);

private:
    int n,m;
};

这里的关键改动:

  • 拆分了avl_node(element层)和avl_node_id(ID层)的独立结构
  • 给avl_node_id新增elem_root指针,专门关联该ID对应的element树
  • 因为两层树的节点结构不同,需要分别实现平衡、旋转、插入方法(比用模板更直观)

2. 实现ID树的插入逻辑

原来的插入方法只能处理单一数据,现在要改成:插入ID时先检查是否已存在——存在则把element插入对应树,不存在则新建ID节点并初始化element树。

insert_id方法实现:

AVLTree::avl_node_id* AVLTree::insert_id(avl_node_id *root, int id_val, int elem_val) {
    if (root == NULL) {
        // 新建ID节点,同时初始化它的element树
        root = new avl_node_id;
        root->id = id_val;
        root->elem_root = insert_element(NULL, elem_val);
        root->left = NULL;
        root->right = NULL;
        return root;
    } else if (id_val < root->id) {
        root->left = insert_id(root->left, id_val, elem_val);
        root = balance_id(root);
    } else if (id_val > root->id) {
        root->right = insert_id(root->right, id_val, elem_val);
        root = balance_id(root);
    } else {
        // ID已存在,直接插入到对应的element树
        root->elem_root = insert_element(root->elem_root, elem_val);
    }
    return root;
}

3. 修正readFile读取逻辑

现在读取文件时,每次读取ID和element,直接调用insert_id即可完成两层树的插入:

void AVLTree::readFile() {
    ifstream read("input2.txt");
    while(read >> n >> m){
        id_root = insert_id(id_root, n, m);
    }
}

4. 补充ID树的平衡方法

ID树的平衡、旋转逻辑和element树完全一致,只是参数换成avl_node_id类型,比如:

int AVLTree::height_id(avl_node_id *node) {
    int h = 0;
    if (node != NULL) {
        int l_height = height_id(node->left);
        int r_height = height_id(node->right);
        int max_height = max(l_height, r_height);
        h = max_height + 1;
    }
    return h;
}

int AVLTree::diff_id(avl_node_id *node) {
    int l_height = height_id(node->left);
    int r_height = height_id(node->right);
    int balance_factor = l_height - r_height;
    return balance_factor;
}

AVLTree::avl_node_id* AVLTree::rr_rotation_id(avl_node_id *parent) {
    avl_node_id *temp;
    temp = parent->right;
    parent->right = temp->left;
    temp->left = parent;
    return temp;
}

// 同理实现ll_rotation_id、lr_rotation_id、rl_rotation_id、balance_id方法

5. 实现整体打印逻辑

要展示整个两层树结构,可以先遍历ID树,每个ID节点打印后,再遍历它关联的element树:

void AVLTree::printToScreen() {
    cout << "ID AVL Tree with Associated Element Trees:\n";
    display_id(id_root, 0);
}

void AVLTree::display_id(avl_node_id *node, int space) {
    if (node == NULL) return;
    space += 5;
    display_id(node->right, space);
    cout << endl;
    for (int i = 5; i < space; i++) cout << " ";
    cout << node->id << endl;
    // 打印当前ID对应的element树
    cout << "    Element Tree for ID " << node->id << ":" << endl;
    display_element(node->elem_root, space + 5);
    display_id(node->left, space);
}

// display_element方法和你原来的display逻辑一致,参数为avl_node*

核心逻辑总结

  • 两层树的关联核心是avl_node_id中的elem_root指针,每个ID节点独立维护自己的element AVL树
  • 插入时区分ID是否存在:不存在则新建ID节点并初始化element树;存在则直接往对应element树插入数据
  • ID树和element树的平衡逻辑完全独立,各自维护AVL树的平衡属性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:42:19