平衡搜索树-AVL树你被问到了吗?

基本概念

特征

  • 二叉树
    • 每个结点只有两个孩子
    • 孩子之间有区别 一般为左孩子和右孩子
  • 二叉搜索树
    • 任取二叉树的结点N,满足 K(N的左子树) < K(N) < K(N的右子树) (也就是左子树的值 < 根节点的值 < 右子树的值)
  • 平衡树
    • 任取树的结点 N,要求左子树的高度和右子树的高度之间的差的绝对值,不能超过1
      H(N.left) - H(N.right) <= 1
      在这里插入图片描述
  • AVL树 (满足上面三种)
    • 二叉树
    • 搜索树
    • 平衡树
      在这里插入图片描述

AVL树结点中需要携带的信息

需要携带至少5中信息
在这里插入图片描述
伪代码表示
在这里插入图片描述

AVL 特点

相对于普通搜索树的优势:
由于平衡,所以一颗搜索树不会退化成单支树的情况,所以可以保护保证时间复杂度 ( O log n)是稳定的。
那么它的其他特点就可以参照搜索树来理解

AVL树的操作

AVL 仍然是一个装元素的容器

添加元素

在这里插入图片描述
插入前
按照普通搜索树的方式进行插入

  • 元素已经在集合中,插入失败
  • 插入成功

插入中
插入一个结点( cur,所以 cur.bf = 0),其父节点的平衡因子需要讨论cur.parent.bf = ?

一个AVL树中 ,任意一个结点,它的平衡因子的取值只可能是-1 0 1.
一个结点,如果插入到父节点的左边 父节点的bf +1 插入到父节点的右边 bf-1。

插入结点之后,首先要判断它的perent 的bf

  • bf == 0 那么 H(parent) 也就是父节点的高度不变
  • bf == 1/ bf == -1 H(parent) 也就是父节点的高度改变 (高度+1 )

为什么要讨论H(parent 是否变化) 重点就是

  • 如果 H(parent) 不变,那么BF(parent.parent) 就不需要变化
  • 如果 H(parent) 变化了,那么BF(parent.parent) 也需要跟着进行调整

插入后

插入的结点是cur ,插入后的父结点只可能有以下两种情况

  • 插入后,满足AVL树的特征且高度(bf = 0)不发生变化,插入结束
    插入过程满足搜索树特征,插入后,bf(parent)满足平衡树特征,同时H(parent) 没有发送变化,对树的影响到此为止,整体满足AVL树插入完成
    在这里插入图片描述

  • 插入后,局部满足AVL树,但因为H(parent)高度+1(bf = -1 /1),所以向当前父结点的父结点(根节点蔓延),停下来的条件
    √ 蔓延过程中 parent .parent == null 说明parent是树的根,插入就结束了。

    √ 如果不是继续调整,调整如下:

    • 蔓延过程中,遇到 df = 0,结束。
      在这里插入图片描述

    • 蔓延到根处就还是情况2-那就继续向上。再次判断是树的根吗?不是就再次调整
      在这里插入图片描述

    • 蔓延过程中,遇到了 (bf = -2 bf = 2) 树失衡结束。
      在这里插入图片描述

失衡问题

结束判断的时候如果树处于失衡条件那么需要进行调整。即bf(parent) = 2/-2

这种情况可以分为以下的四大类

  1. 左 左 失衡
    表示从失衡结点出发 一直向左走的失衡
    在这里插入图片描述

直接对左左失衡的结点进行右旋

  1. 左 右 失衡
    在这里插入图片描述

  2. 右 右 失衡
    在这里插入图片描述

  3. 右 左 失衡
    在这里插入图片描述

除了失衡结点之外,其他的部分不会出现失衡的情况。要始终记得一句话,就是失衡是慢慢往上蔓延的。

反推绿色:如果再绿色的部分(也就是过程中出现了失衡,那么是轮不到调整当前的失衡结点的,从下蔓延,再过程中就阻塞了,到不了失衡结点)

在这里插入图片描述

解决失衡问题必须满足的条件:

  • Tree(失衡结点) 满足AVL树(搜索 + 平衡)
  • 修复完之后的Tree (失衡的树) 高度和插入前保持不变
    在这里插入图片描述

旋转操作

要想解决这个问题,必须先对树的旋转有了解。

搜索树的旋转

右旋
在这里插入图片描述
左旋
在这里插入图片描述
搜索树的左右旋转示意
在这里插入图片描述

AVL树的旋转
左左失衡
  1. 左左失衡解决办法:对失衡的结点进行右旋操作
    在这里插入图片描述

那么是否在通用的场景下,这个办法仍然正确
证明左左失衡情况下,对失衡结点右旋后能够做到验证以下两点成立即可。

  • 局部满足AVL树(搜索树 + 平衡)
  • 失衡树的高度不变
    讨论插入橙色的结点之后,H(甲)和H(乙) 的关系 (没有插入橙色的结点之前 这颗树一定是一个AVL树)

在这里插入图片描述

1.假设一:插入结点之后 H(甲) = H(乙)
反证法发现 没有插入结点之前不是AVL树,所以假设一错误
在这里插入图片描述

  1. 假设二:插入结点之后 H(甲)< H(乙)
    反证法发现 没有插入结点之前不是AVL树,所以假设二错误
    在这里插入图片描述

  2. 假设三:插入结点之后 H(甲) > H(乙)
    反证法发现 没有插入结点之前是AVL树,所以假设三成立!
    在这里插入图片描述

上述验证之后,各个的高度都知道了,经过右旋以后
在这里插入图片描述

左右失衡

首先对失衡的结点的左孩子进行左旋,再对失衡结点进行右旋。
注意是对左孩子进行变动失衡节点是不动的!

在这里插入图片描述

右右失衡

在这里插入图片描述

右左失衡

在这里插入图片描述

总结
失衡状态调整策略
左左失衡对失衡结点右旋
左右失衡对失衡结点的左孩子左旋 然后失衡结点右旋
右右失衡对失衡结点左旋
右左失衡对失衡结点的右孩子右旋 失衡结点进行左旋

查找元素

和普通搜索树的查找完全一致

  • 判断是否存在 key == node.key 找到
  • 获取管理数据 Value
    key < node.key 往左找
    key > node.key 往右找
    如果最后走到null 就没有找到

删除元素

由于比较复杂,暂时不研究。

时间复杂度评估

查找 最坏是树的高度 (log n)
插入 (查找位置 + 插入+调整) ( log n)
在这里插入图片描述
删除(log n)

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值