数据结构 -- AVL树

AVL树

  • AVL树是带平衡条件的平衡二叉树
  • 平衡条件:其每个节点的左子树和右子树的高度
  • 这是一个AVL树
    在这里插入图片描述
  • 这就不是一个AVL树了
    在这里插入图片描述

解决AVL树插入节点后破坏平衡条件

  • 通过旋转方式改变AVL树的节点,达到平衡。
  • 我们把必须重新平衡的节点叫做a,由于任意节点最多有两个儿子,因此出现高度不平衡就需要a点的两棵子树的高度差2,容易看出这种不平衡可能出现在下面四种情况中:
  • 1、对a的左儿子的左子树进行一次插入 – (左 - 左)
  • 2、对a的左儿子的右子树进行一次插入 – (左 - 右)
  • 3、对a的右儿子的左子树进行一次插入 – (右 - 左)
  • 4、对a的右儿子的右子树进行一次插入 – (右 - 右)
其中对于 1和4 我们采用单旋转,对于2和3我们采用双旋转来解决这个问题,实现新的AVL树

单旋转

插入节点6之后整个avl树破坏了平衡节点,在节点8处。这里的a就是8。这里属于(左- 左)情况,我们将8节点定义为k1,将7节点定义为k2,现在将k2放到k1的位置,解决了。
在这里插入图片描述
在这里插入图片描述

  • 同理对于情形4也是同理
  • 小结:我们将a节点设为k1,将a节点的下一个节点设为k2,之后将k2的位置放到k1后,重新节点分配就形成了新的AVL树,这里还有一个小知识点是当插入的节点数值不在k1和k2之间时,那么就会是情形1和情形4,同时用单旋转解决。

双旋转

  • 这里用于解决情形2和情形3(也就是左-右和右-左)。双旋转实际上就是两次单旋转
  • 这里将a(7)设为k1,k1下面的点为k3,k3下面的点为k2。将k2的节点放到a的位置上,其他节点重新排布。造成需要双旋转的节点的数值一定在k1和k3之间
    在这里插入图片描述
  • 在这里7是k1,16是k3,15是k2。
  • 按照上述步骤解决,这个是右-左,同理左-右也是一样的。
    在这里插入图片描述

实现代码

AVL树的数据结构
  • 这是一个内部类
public static class AvlNode<T>{
    
    AvlNode node;
    AvlNode<T> rnode;
    AvlNode<T> lnode;
    Integer height;
    AvlNode(AvlNode node){
        this(node,null,null);
    }
    AvlNode(AvlNode node,AvlNode<T> lnode,AvlNode<T> rnode){
        this.node = node;
        this.rnode = rnode;
        this.lnode = lnode;
    }
}
单旋转
  • 这里面相当于是传入节点的左边部分放到上面,交换节点。
 private AvlNode<T> rotateWithLeftChild(AvlNode<T> k2){
   AvlNode<T> k1 = k2.lnode;
   k2.lnode = k1.rnode;
   k1.rnode = k2;
   k2.height = Math.max(height(k2.lnode),height(k2.rnode))+1;
   k1.height = Math.max(height(k1.lnode),height(k1.rnode))+1;
   return k1;
}
  • 同理,右边旋转
private AvlNode<T> rotateWithRightChild(AvlNode<T> k2){
   AvlNode<t> k1 = k2.rnode;
   k2.rnode = k1.lnode;
   k1.lnode = k2;
   k2.height = Math.max(height(k2.lnode),height(k2.rnode))+1;
   k1.height = Math.max(height(k1.lnode),height(k1.rnode))+1;
   return k1;
}
计算高度
public Integer height(AvlNode<T> t ){
   return t == null?-1:t.height;
}
双旋转
private AvlNode<T> doubleWithLeftChild(AvlNode<T> k3){
   k3.lnode = rotateWithRightChild(k3.lnode);
   return rotateWithLeftChild(k3);
}
private AvlNode<T> doubleWithRightChild(AvlNode<T> k3){
   k3.lnode = rotateWithLeftChild(k3.lnode);
    return rotateWithRightChild(k3)
}
发布了134 篇原创文章 · 获赞 91 · 访问量 16万+

猜你喜欢

转载自blog.csdn.net/weixin_44588495/article/details/102773661
今日推荐