Algorithm AVL树-旋转异常:破坏BST属性

Algorithm AVL树-旋转异常:破坏BST属性,algorithm,binary-search-tree,avl-tree,Algorithm,Binary Search Tree,Avl Tree,当我在处理AVL树实现时,我遇到了一个案例,旋转破坏了BST属性 我很确定我做错了什么,但我不知道是什么 我将41、49、21和47插入AVL树。当我再次添加49时,它表示“失衡”,如下所示 (Out of balance !!!) ( at 49 L-R ) 41 41 / \ / \ 21 49 => 21

当我在处理AVL树实现时,我遇到了一个案例,旋转破坏了BST属性

我很确定我做错了什么,但我不知道是什么

我将41、49、21和47插入AVL树。当我再次添加49时,它表示“失衡”,如下所示

                 (Out of balance !!!)
                 (   at 49 L-R      )
     41                41
    /  \              /  \
   21   49  =>      21    49
       /                 /
      47               47
                         \
                          49
因此我试着向左旋转47圈,向右旋转49圈,如下图所示

          Rotate 47         Rotate 49
           to Left          to Right 
     41               41                 41
    /  \     =>      /  \      =>       /  \  
   21   49         21    49           21    49 
       /                /                  /  \
      47               49                47    49
        \             /
         49          47
树的平衡性更好,但我认为我打破了右下子树的BST属性,在49的右侧有49个

    49
   /  \
  47  49
我认为平衡这棵树的最好方法是跟随

     47
    /  \
  41    49
  /    /
21   49
但我不知道如何使用41-49-21-47-49数字加法序列到达那里。也许这不是正确的结果,但我在这里迷路了

最佳结果是什么?我应该如何实现

有人能告诉我我做错了什么吗


非常感谢

对于您的情况,如果键和值重合,则可能如下所示。假设您的节点类如下所示:

class Node {
    int value;     //Value
    int height;    //Height
    Node left;     //Left child
    Node right;    //Right child
    int count = 1; //keeps track of how many duplicate values were inserted
}
然后,当插入一个新值时,如果有一个新值等于当前节点的值,则可以增加
count
。下面是我对AVL树插入的实现:

public Node insert(Node root, int value) {
    if (root == null) {
        root = new Node();
        root.value = value;
        return root;
    } else if (root.value > value) {
        root.left = insert(root.left, value);
        root.height = Math.max(root.height, root.left.height + 1);
    } else if (root.value < value) {
        root.right = insert(root.right, value);
        root.height = Math.max(root.height, root.right.height + 1);
    } else {
        // consider duplicates the same node
        root.count++;
    }

    Node a = root;
    //left subtree must be rebalanced
    if (balanceFactor(root) == 2) {
        Node b = a.left;
        //it's a left left case
        if (balanceFactor(b) == 1) {
            Node b2 = b.right;
            b.right = a;
            a.left = b2;
            a.height = getHeight(a);
            b.height = getHeight(b);
            return b;
        } else {//it's a left right case
            Node c = b.right;
            Node c1 = c.left;
            Node c2 = c.right;
            a.left = c2;
            c.right = a;
            c.left = b;
            b.right = c1;
            a.height = getHeight(a);
            b.height = getHeight(b);
            c.height = getHeight(c);
            return c;
        }
    } else if (balanceFactor(root) == -2) {//right subtree must be rebalanced
        Node b = a.right;
        //it's a left left case
        if (balanceFactor(b) == -1) {
            Node b1 = b.left;
            b.left = a;
            a.right = b1;
            a.height = getHeight(a);
            b.height = getHeight(b);
            return b;
        } else {//it's a left right case
            Node c = b.left;
            Node c1 = c.left;
            Node c2 = c.right;
            c.right = b;
            c.left = a;
            b.left = c2;
            a.right = c1;
            a.height = getHeight(a);
            b.height = getHeight(b);
            c.height = getHeight(c);
            return c;
        }
    }

    return root;
}

private static int getHeight(Node node) {
    int l = (node.left == null ? 0 : node.left.height + 1);
    int r = (node.right == null ? 0 : node.right.height + 1);
    return Math.max(l, r);
}

private static int balanceFactor(Node node) {
    int left = node.left == null ? -1 : node.left.height;
    int right = node.right == null ? -1 : node.right.height;

    return left - right;
}
公共节点插入(节点根,int值){
if(root==null){
根=新节点();
root.value=值;
返回根;
}else if(root.value>value){
root.left=插入(root.left,值);
root.height=Math.max(root.height,root.left.height+1);
}else if(root.value

这样,你就不会再有重复的了:)

你实际上没有做错什么

在评论中,你们说“我认为L边小于或等于当前节点值,R边大于当前节点值。我错了吗?”

…是的,你错了

对于具有重复值的树,右分支仅包含严格较大元素的条件与平衡操作不兼容。尝试以下方法:将相同值的20个副本链接到一个树中。如果只能链接左侧的相等值,则必须创建一个单独链接的列表。你的树将有20层深,完全不平衡

考虑树中重复值的方法是,树中实际上没有任何重复值:-)BST定义了一个总排序,而有效的再平衡操作(如旋转)保留了这个总排序

当您将第二个
49
插入到树中时,您将把它放在第一个
49
的左侧或右侧。如果你把它放在左边,那么它将根据树的顺序变小,并且在任何再平衡之后它总是变小。如果你把它放在右边,那么它会更大,并且会根据树的顺序保持更大

如果你想一想,它必须是这样的,因为平衡操作甚至不看节点中的值。它们链接在一起的方式决定了顺序,并且顺序不会改变