AVL 树

AVL树是一种自平衡二叉搜索树,确保任何节点的两个子树的高度差不超过1,从而保证了查找、插入和删除等操作的时间复杂度为O(logn)。文章详细介绍了AVL树的节点高度、平衡因子、旋转操作(右旋、左旋、先左后右、先右后左)以及插入和删除节点的处理,展示了其在数据结构和算法中的重要应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

介绍

结点高度

结点平衡因子

AVL 树旋转

右旋

左旋

先左后右

先右后左

旋转的选择

插入结点

删除结点

查找结点

AVL 树典型应用


  • 介绍

  • 在进行多次插入与删除操作后,二叉搜索树可能会退化为链表
  • 此时所有操作的时间复杂度都会由 𝑂(log 𝑛) 劣化至 𝑂(𝑛)
  • 如下图所示,执行两步删除结点后,该二叉搜索树就会退化为链表

  • 再比如,在以下完美二叉树中插入两个结点后,树严重向左偏斜,查找操作的时间复杂度也随之发生劣化

  • 而在不断添加与删除结点后,AVL 树仍然不会发生退化,进而使得各种操作的时间复杂度均能保持在 𝑂(log 𝑛) 级别
  • 换言之,在频繁增删查改的使用场景中,AVL 树可始终保持很高的数据增删查改效率,具有很好的应用价值
  • 「AVL 树」既是「二叉搜索树」又是「平衡二叉树」,同时满足这两种二叉树的所有性质,因此又被称为「平衡二叉搜索树」
  • 结点高度

  • 在 AVL 树的操作中,需要获取结点「高度 Height」,所以给 AVL 树的结点类添加 height 变量

  • 「结点高度」是最远叶结点到该结点的距离,即走过的「边」的数量
  • 需要特别注意,叶结点的高度为 0 ,空结点的高度为 ‑1
  • 封装两个工具函数,分别用于获取与更新结点的高度

  • 结点平衡因子

  • 结点的「平衡因子 Balance Factor」是 结点的左子树高度减去右子树高度,并定义空结点的平衡因子为 0
  • 同样地,将获取结点平衡因子封装成函数,以便后续使用

  • 设平衡因子为 𝑓 ,则一棵 AVL 树的任意结点的平衡因子皆满足 −1 ≤ 𝑓 ≤ 1
  • AVL 树旋转

  • AVL 树的独特之处在于「旋转 Rotation」的操作,其可在不影响二叉树中序遍历序列的前提下,使失衡结点重新恢复平衡
  • 换言之,旋转操作既可以使树保持为「二叉搜索树」,也可以使树重新恢复为「平衡二叉树」
  • 将平衡因子的绝对值 > 1 的结点称为「失衡结点」
  • 根据结点的失衡情况,旋转操作分为 右旋、左旋、先右旋后左旋、先左旋后右旋
  • 右旋

  • 如下图所示(结点下方为「平衡因子」),从底至顶看,二叉树中首个失衡结点是 结点 3
  • 聚焦在以该失衡结点为根结点的子树上,将该结点记为 node ,将其左子结点记为 child ,执行「右旋」操作
  • 完成右旋后,该子树已经恢复平衡,并且仍然为二叉搜索树
  • 进而,如果结点 child 本身有右子结点(记为 grandChild ),则需要在「右旋」中添加一步:将 grandChild 作为 node 的左子结点
  • “向右旋转”是一种形象化的说法,实际需要通过修改结点指针实现,代码如下所示

  • 左旋

  • 类似地,如果将取上述失衡二叉树的“镜像”,那么则需要「左旋」操作

  • 同理,若结点 child 本身有左子结点(记为 grandChild ),则需要在「左旋」中添加一步:将 grandChild 作为node 的右子结点

  • 观察发现,「左旋」和「右旋」操作是镜像对称的,两者对应解决的两种失衡情况也是对称的
  • 根据对称性,可以很方便地从「右旋」推导出「左旋」
  • 具体地,只需将「右旋」代码中的把所有的 left 替换为 right 、所有的 right 替换为 left ,即可得到「左旋」代码

  • 先左后右

  • 对于下图的失衡结点 3 ,单一使用左旋或右旋都无法使子树恢复平衡
  • 此时需要「先左旋后右旋」,即先对child 执行「左旋」,再对 node 执行「右旋」

  • 先右后左

  • 同理,取以上失衡二叉树的镜像,则需要「先右旋后左旋」,即先对 child 执行「右旋」,然后对 node 执行「左旋」

  • 旋转的选择

  • 下图描述的四种失衡情况与上述 Cases 逐个对应,分别需采用 右旋、左旋、先右后左、先左后右 的旋转操作

  • 具体地,在代码中使用失衡结点的平衡因子、较高一侧子结点的平衡因子 来确定失衡结点属于上图中的哪种情况

  • 为方便使用,将旋转操作封装成一个函数
  • 至此可以使用此函数来旋转各种失衡情况,使失衡结点重新恢复平衡

  • 插入结点

  • 「AVL 树」的结点插入操作与「二叉搜索树」主体类似
  • 不同的是,在插入结点后,从该结点到根结点的路径上会出现一系列「失衡结点」
  • 所以需要从该结点开始,从底至顶地执行旋转操作,使所有失衡结点恢复平衡

  • 删除结点

  • 「AVL 树」删除结点操作与「二叉搜索树」删除结点操作总体相同
  • 类似地,在删除结点后,也需要从底至顶地执行旋转操作,使所有失衡结点恢复平衡
  • 查找结点

  • 「AVL 树」的结点查找操作与「二叉搜索树」一致,在此不再赘述
  • AVL 树典型应用

  • 组织存储大型数据,适用于高频查找、低频增删场景
  • 用于建立数据库中的索引系统
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

兔子队列

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

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

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

打赏作者

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

抵扣说明:

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

余额充值