Data structures 平衡AVL树
我无法平衡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树中的关键不变量是每个节点的平衡因子为-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表示单个节点,而不是子树。我应该更清楚我的符号。这有意义吗?