Data structures 平衡AVL树

Data structures 平衡AVL树,data-structures,tree,rotation,binary-search-tree,avl-tree,Data Structures,Tree,Rotation,Binary Search Tree,Avl Tree,我无法平衡AVL树。我到处寻找如何平衡它们的步骤,但我就是找不到任何有用的东西 我知道有四种: 单左旋转 单右旋转 左右双旋转 左右双旋转 但是我就是不知道如何选择它们中的哪一个,以及在哪个节点上应用它 任何帮助都将不胜感激 AVL树中的关键不变量是每个节点的平衡因子为-1、0或+1。这里,“平衡因子”是左右子树之间的高度差+1表示左子树比右子树高一个,-1表示左子树比右子树短一个,0表示子树大小相同。这些信息通常缓存在每个节点中 当获得平衡因子为-2或+2的节点时,需要进行旋转。当需要旋转

我无法平衡AVL树。我到处寻找如何平衡它们的步骤,但我就是找不到任何有用的东西

我知道有四种:

  • 单左旋转
  • 单右旋转
  • 左右双旋转
  • 左右双旋转
但是我就是不知道如何选择它们中的哪一个,以及在哪个节点上应用它


任何帮助都将不胜感激

AVL树中的关键不变量是每个节点的平衡因子为-1、0或+1。这里,“平衡因子”是左右子树之间的高度差+1表示左子树比右子树高一个,-1表示左子树比右子树短一个,0表示子树大小相同。这些信息通常缓存在每个节点中

当获得平衡因子为-2或+2的节点时,需要进行旋转。当需要旋转时,这里有一种可能的设置:

          u (-2)
         / \
        A   v (-1)
           / \
          B   C
如果我们把这些树的高度填上,我们就会

          u h + 2
         / \
    h-1 A   v h + 1
           / \
      h-1 B   C h
如果发生这种情况,进行一次向右旋转将产生

         v h+1
        / \ 
     h u   C h
      / \
 h-1 A   B h-1
嘿!这棵树是平衡的。这棵树的镜像也可以通过一次向左旋转来修复

所有AVL树旋转都可以简单地通过列举小范围内可能的平衡因子,然后确定每个步骤应应用哪些旋转来确定。我将把这个作为练习留给读者。:-)如果您只想查找答案,则有一张很好的图片,其中总结了可能需要应用的所有旋转


希望这有帮助

这是java实现,您将了解该算法:

private Node<T> rotate(Node<T> n) {
    if(n.getBf() < -1){
            if(n.getRight().getBf() <= 0){
                return left(n);         
            }
            if(n.getRight().getBf() > 0){
                return rightLeft(n);
            }
    }   
    if(n.getBf() > 1){
            if(n.getLeft().getBf() >= 0){
                return right(n);
            }
            if(n.getLeft().getBf() <  0){
                return leftRight(n);
            }
    }
    return n;
}
专用节点旋转(节点n){
如果(n.getBf()<-1){
if(n.getRight().getBf()0){
返回右向左(n);
}
}   
如果(n.getBf()>1){
如果(n.getLeft().getBf()>=0){
返回权(n);
}
if(n.getLeft().getBf()<0){
返回leftRight(n);
}
}
返回n;
}
4次旋转的单独方法如下:

/**
 * Performs a left rotation on a node
 * 
 * @param n The node to have the left rotation performed on
 * @return The new root of the subtree that is now balanced due to the rotation
 */
private Node<T> left(Node<T> n) {
    if(n != null){
        Node<T> temp = n.getRight();
        n.setRight(temp.getLeft());
        temp.setLeft(n);
        return temp;
    }
    return n;   
}

/**
 * Performs a right rotation on a node
 * 
 * @param n The node to have the right rotation performed on
 * @return The new root of the subtree that is now balanced due to the rotation
 */
private Node<T> right(Node<T> n) {
    if(n != null){
        Node<T> temp = n.getLeft();
        n.setLeft(temp.getRight());
        temp.setRight(n);
        return temp;
    }
    return n;
}

/**
 * Performs a left right rotation on a node
 * 
 * @param n The node to have the left right rotation performed on
 * @return The new root of the subtree that is now balanced due to the rotation
 */
private Node<T> leftRight(Node<T> n) {
    n.setLeft(left(n.getLeft()));
    Node<T> temp = right(n);
    return temp;
}

/**
 * Performs a right left rotation on a node
 * 
 * @param n The node to have the right left rotation performed on
 * @return The new root of the subtree that is now balanced due to the rotation
 */
private Node<T> rightLeft(Node<T> n) {
    n.setRight(right(n.getRight()));
    Node<T> temp = left(n);
    return temp;
}
/**
*在节点上执行左旋转
* 
*@param n要在其上执行左旋转的节点
*@返回由于旋转而平衡的子树的新根
*/
专用节点左(节点n){
如果(n!=null){
节点温度=n.getRight();
n、 setRight(temp.getLeft());
左置温度(n);
返回温度;
}
返回n;
}
/**
*在节点上执行右旋转
* 
*@param n要在其上执行右旋转的节点
*@返回由于旋转而平衡的子树的新根
*/
专用节点权限(节点n){
如果(n!=null){
节点温度=n.getLeft();
n、 setLeft(temp.getRight());
温度设置权(n);
返回温度;
}
返回n;
}
/**
*在节点上执行左右旋转
* 
*@param n要在其上执行左右旋转的节点
*@返回由于旋转而平衡的子树的新根
*/
专用节点leftRight(节点n){
n、 setLeft(左)(n.getLeft());
节点温度=右侧(n);
返回温度;
}
/**
*在节点上执行左右旋转
* 
*@param n要在其上执行左右旋转的节点
*@返回由于旋转而平衡的子树的新根
*/
专用节点rightleeft(节点n){
n、 setRight(right)(n.getRight());
节点温度=左侧(n);
返回温度;
}

这棵树不是已经平衡了吗?u+A=2,u+v+c=3,2-3=-1,那么它是平衡的。为什么我们要在这里旋转?@user1910524-不,这棵树不平衡。请注意,其左子树和右子树的高度相差2-左子树的高度为h-1,右子树的高度为h+1。请记住,平衡因子表示两棵树之间的高度差,因此说“u+A=2”不是一个有意义的计算。这有意义吗?@templatetypedef,我不明白。如果我们看“u”的左子树,我们会发现级别=2。如果我们看“u”的右子树,我们会发现级别=3。所以2-3=-1。如果我们看“v”的左子树,我们会发现级别=2。如果我们看“v”的右子树,我们会发现级别=s。所以2-2=0。所以这棵树是平衡的@用户1910524-哦,我明白了。A、 B和C表示特定高度的任意子树,而不是单个节点。u和v表示单个节点,而不是子树。我应该更清楚我的符号。这有意义吗?