查找树-- AVLTree 【 自平衡二叉查找树 】 的原理图解及示例代码

1 AVL 树

1.1 概念

AVL树是最先发明的自平衡二叉查找树
在AVL树中任何节点的两个子树的高度最大差别为1,也被称为高度平衡树。
增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。
AVL树得名于它的发明者G. M. Adelson-Velsky和E. M. Landis,他们在1962年的论文《An algorithm for the organization of information》中发表了它
AVL 树 = Adelson-Velsky Landis Tree

1.2 AVL树的特点

  • 本身首先是一棵二叉搜索树。
  • 带有平衡条件:每个结点的左右子树的高度之差的绝对值即平衡因子 <= 1

AVL树,本质上是带了自动平衡功能的二叉查找树

1.3 AVL 旋转

共有4种旋转:

  • 右旋
  • 左旋
  • 双向旋转
    • 先左后右
    • 先右后转

单向右旋平衡处理LL

在*T的左子树的左子树上插入结点,T的平衡因子由1增至2,致使以T为根的子树失去平衡,则需进行一次右旋转操作
T向右旋转成为L的右结点,同时,Y放到T的左孩子上
在这里插入图片描述

单向左旋平衡处理RR

在*T的右子树的右子树上插入结点,T的平衡因子由1增至2,致使以T为根的子树失去平衡,则需进行一次左旋转操作
T向左旋转成为R的左结点,同时,Y放到T的右孩子上
在这里插入图片描述

双向旋转(先左后右)平衡处理LR

先达到左旋的条件,旋转后又达到右旋的条件
在这里插入图片描述

双向旋转(先右后左)平衡处理RL

先达到右旋的条件,旋转后又达到左旋的条件
在这里插入图片描述

1.4 节点删除

AVL树删除节点的过程是,先找到该节点,然后进行删除。
由于删除节点的位置不同,导致删除后节点进行移动的方式不同。
删除节点的位置分为以下4类:

  • 删除叶子结点。操作:直接删除,然后依次向上调整为AVL树。
  • 删除非叶子节点,该节点只有左孩子。操作:该节点的值替换为左孩子节点的值,然后删除左孩子节点。
    • 左孩子节点为叶子结点,所以删除左孩子节点的情况为第1种情况。
    • 为什么左孩子节点为叶子节点?,因为删除节点前,该树是AVL树,由AVL树的定义知,每个节点的左右子树的高度差的绝对值<=1,由于该节点只有左孩子,没有右孩子,如果左孩子还有子节点,那么将不满足每个节点的左右子树的高度差的绝对值<=1,所以左孩子节点为叶子结点
  • 删除非叶子节点,该节点只有右孩子。操作:该节点的值替换为右孩子节点的值,然后删除右孩子节点。
    • 右孩子节点为叶子结点,所以删除右孩子节点的情况为第1种情况。
    • 为什么右孩子节点为叶子节点?答案和第二种情况一样】
  • 删除非叶子节点,该节点既有左孩子,又有右孩子。操作:该节点的值替换为该节点的前驱节点(或者后继节点),然后删除前驱节点(或者后继节点)。
    • 前驱结点:在中序遍历中,一个节点的前驱结点,先找到该节点的左孩子节点,再找左孩子节点的最后一个右孩子节点。向左走一步,然后向右走到头。最后一个右孩子节点即为前驱节点
    • 后继节点:在中序遍历中,一个节点的后继结点,先找到该节点的右孩子节点,再找右孩子节点的最后一个左孩子节点。向右走一步,然后向左走到头。最后一个左孩子节点即为前驱节点

总结:对于非叶子节点的删除,最终都将转化为对叶子节点的删除。

删除叶子节点

在这里插入图片描述

删除非叶子节点,该节点只有左孩子

在这里插入图片描述

删除非叶子节点,该节点只有右孩子

在这里插入图片描述

删除非叶子节点(既有左孩子,又有右孩子)

在这里插入图片描述

2 源码示例

感兴趣的同学,可以直接参考如下源码学习

2.1 scala中的实现

在scala 2.11.x版本中,在AVLTree 类中实现了AVL树
但表示即将从标准库中删除,理由是和红黑树的差异不明显
AVLTree and its related classes are being removed from the standard library since they’re not different enough from RedBlackTree to justify keeping them

2.2 common-math3中的实现

在common-math3库中实现了AVLTree, 具体实现类是:org.apache.commons.math3.geometry.partitioning.utilities.AVLTree
目前标记为@Deprecated

org.apache.commons
commons-math3
3.6.1

2.3 Guava中的实现

在guava库中实现了AVLTree,具体实现类是:com.google.common.collect.TreeMultiset中的一个静态内部类 AvlNode

com.google.guava
guava
18.0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

enjoy编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值