AVL树没有正确平衡

时间:2017-12-04 05:04:11

标签: c avl-tree

我有一个编写自平衡二叉搜索树的任务。我决定使用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是旋转第一个后修复方向然后第二个后修复方向的基本函数,并且它们都依赖于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类似,但调整为右旋。

我想知道这段代码在哪里混乱,以至于它不会产生所需的输出。

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

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

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

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