简体   繁体   English

AVL树无法正确平衡

[英]AVL tree not balancing correctly

I have an assignment to write a self balancing binary search tree. 我分配了一个自平衡二进制搜索树。 I decided to use an AVL tree as it is what we have discussed in class. 我决定使用AVL树,因为这是我们在课堂上讨论的。 Then with the given input of { 3, 5, 61, 9, 32, 7, 1, 45, 26, 6} I'm expecting an output of: 然后,使用给定输入{3,5,61,9,32,7,1,45,26,6},我期望输出为:

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

That is, unless I have grossly misunderstood and thus miscalculated what an AVL tree is supposed to do when it balances itself. 也就是说,除非我被严重误解并因此错误地计算了AVL树在平衡时应该做的事情。 The output I'm getting is quite different: 我得到的输出是完全不同的:

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

Again, unless I am completely wrong, that tree is not balanced. 再说一次,除非我完全错了,否则那棵树是不平衡的。 The function I'm using to set up the tree is defined as such: 我用来建立树的功能定义如下:

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;
}

The structure I'm using to store all the data is defined as such: 我用来存储所有数据的结构定义如下:

typedef struct node
{

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

    int data;

    int height;
} node;

The functions rotate_left_right and rotate_right_left are basic functions that rotate the direction of the first post-fix then the second post-fix, and are both reliant on rotate_left and rotate_right for their respective direction. 函数rotate_left_right和rotate_right_left是基本功能,可旋转第一个后缀的方向,然后旋转第二个后缀的方向,并且它们各自的方向都依赖于rotate_left和rotate_right。 rotate left is defined as such: 向左旋转的定义如下:

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 is similar but adjusted for a rotation right. rotation_right相似,但针对旋转右数进行了调整。

I'm wondering where this code messes up so that it doesn't produce the desired output. 我想知道这段代码在哪里弄乱了,这样就不会产生想要的输出。

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

I don't have a full answer and I'm not sure your code is salvageable, since it misses a lot of pieces. 我没有一个完整的答案,我不确定您的代码是否可挽救,因为它遗漏了很多内容。 Main source of surprise is the missing initialization of cmpVal which is then compared to 2. But if n is NULL its UB. 令人惊讶的主要原因是缺少cmpVal的初始化,然后将其与2进行比较。但是,如果n为NULL其UB。

cmpVal is the balance of AVL but with an absolute value. cmpVal是AVL的余额,但具有绝对值。 Unfortunately when rebalancing you check the existence of a left child or of a right child. 不幸的是,在重新平衡时,您检查是否存在左孩子或右孩子。 But this tells you nothing. 但是,这没有告诉您。 You need to know the sign of the balance in order to choose the rotation direction. 您需要知道天平的符号才能选择旋转方向。 You can have both children and still need to balance. 您可以有两个孩子,但仍然需要保持平衡。

Your insertion looks strange because after checking that the node is not NULL you check the children for the same thing. 您的插入看起来很奇怪,因为在检查节点不为NULL之后,您会检查子节点是否存在相同的事物。 But recursion here would have saved the two checks entirely by performing the check for you. 但是,这里递归通过为您执行检查可以完全保存这两个检查。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM