【问题标题】:AVL tree not balancing correctlyAVL 树没有正确平衡
【发布时间】:2017-12-30 08:16:30
【问题描述】:

我有一个任务是编写一个自平衡二叉搜索树。我决定使用 AVL 树,因为它是我们在课堂上讨论过的。然后使用给定的输入 { 3, 5, 61, 9, 32, 7, 1, 45, 26, 6} 我期待输出:

               7
         6-----|-----32
    3----|      9----|----45
1---|           |---26    |---61

也就是说,除非我严重误解并因此错误地计算了 AVL 树在平衡自身时应该做什么。我得到的输出完全不同:

              5
        3-----|-----61
   1----|      9----|
           7---|---32
        6--|    26--|--45

再一次,除非我完全错了,否则那棵树是不平衡的。我用来设置树的函数是这样定义的:

node* insertKeyAVL(node* n, int e)
{
    int cmpVal;

    if (n == NULL){
            n = create_node();
            n->data = e;
    } else if (e < n->data) {
            if (n->left == NULL){
                    n->left = create_node();
                    n->left->data = e;
                    n->left->parent = n;
            } else {
                    n->left = insertKeyAVL(n->left, e);
            }

            cmpVal = height(n->left) - height(n->right);


    } else {
            if (n->right == NULL){
                    n->right = create_node();
                    n->right->data = e;
                    n->right->parent = n;
            } else {
                    n->right = insertKeyAVL(n->right, e);
            }

            cmpVal = height(n->right) - height(n->left);
    }

    if (cmpVal > 2){
            if (n->left){
                    if (e < n->left->data)
                            n = rotate_left(n);
                    else
                            n = rotate_right_left(n);
            } else if (n->right){
                    if (e > n->right->data)
                            n = rotate_right(n);
                    else
                            n = rotate_left_right(n);
            }
    }

    n->height = max(height(n->left), height(n->right)) + 1;

    return n;
}

我用来存储所有数据的结构是这样定义的:

typedef struct node
{

    struct node *parent;
    struct node*  left;
    struct node*  right;

    int data;

    int height;
} node;

函数 rotate_left_right 和 rotate_right_left 是旋转第一个 post-fix 然后第二个 post-fix 方向的基本函数,它们各自的方向都依赖于 rotate_left 和 rotate_right。向左旋转定义如下:

node* rotate_left(node* n)
{
    node* tmp = n->left;
    n->left = tmp->right;
    tmp->right = n;

    tmp->parent = n->parent;
    n->parent = tmp;

    n->height = max(height(n->left), height(n->right)) + 1;
    tmp->height = max(height(tmp->left), n->height) + 1;

    return tmp;
}

rotate_right 类似,但调整为向右旋转。

我想知道这段代码在哪里搞砸了,所以它不会产生所需的输出。

【问题讨论】:

标签: c avl-tree


【解决方案1】:

当您在预期结果 cmpval 中添加 26 时,5 变为 2,这是无效的,这就是代码重新执行并给出您的结果的原因。

【讨论】:

  • 如果我将 if (cmpVal &gt; 2) 更改为 if (cmpVal &gt; 1) 在插入期间平衡 45 时会出现段错误
【解决方案2】:

我没有完整的答案,我不确定您的代码是否可以挽救,因为它遗漏了很多部分。令人惊讶的主要来源是 cmpVal 缺少初始化,然后将其与 2 进行比较。但如果 n 是 NULL 它的 UB。

cmpVal 是 AVL 的余额,但具有绝对值。不幸的是,在重新平衡时,您会检查左孩子或右孩子的存在。但这什么也没告诉你。您需要知道天平的符号才能选择旋转方向。您可以同时拥有两个孩子,但仍然需要平衡。

您的插入看起来很奇怪,因为在检查节点不为 NULL 之后,您检查子节点是否相同。但是这里的递归会通过为您执行检查来完全保存这两个检查。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-13
    • 2014-01-29
    • 1970-01-01
    相关资源
    最近更新 更多