当前位置: 首页 > news >正文

AVL树(2):

我们之前讲AVL树,我们讲到了旋转,然后讲了左单旋和右单旋。

但是我们这里的单旋产生的条件都是纯粹的一边比较高,

我们看上面这个图片,当我们插入新的结点导致一边的子树比较高的时候,我们必须是存粹的一边高,和图片上面的几个一样,图片下面的几个就不行。

我们看图片中下面的,当我们插入一个结点,结点里面的key(可能是存单个数据的搜索二叉树set,也可能是存一对数据的搜索二叉树,但是维持我们的搜索二叉树的本质的还是要看我们的key)比我们的5大的时候,这时候我们把他插入到我们的5结点的右子树的位置上。这时候他就不是我们的存粹的一边高了。这时候我们看他的根节点的左子树比右子树要高,根节点的平衡因子就是-2,这时候虽然左边子树高度有问题,但是我们不能直接的进行右旋,他不满足我们的“存粹的一边高”。

所以面对这种情况,我们就要学习新的旋转了;

左右双旋:

这个是我们的左右双旋的抽象图;

首先看当我们的h高度为0的时候:

我们看这个图片:开始的时候,我们是右10和5两个结点,然后我们这时候要给二叉树插入一个新的结点,结点的大小比5要大,这时候他就被插入到5结点的右边去了。

这时候我们的10结点的平衡因子是-2,这时候平衡因子出了问题,我们就要进行旋转,我们先看根节点10的左子树,这棵的右边是冗余的,这时候我们把5这个结点作为我们的旋转点进行左旋,左旋后的结果是我们的第三个图片,这时候它就变成单纯的一边高了,这时候我们就把10最为我们的旋转点,然后进行一个右旋,这时候得到我们的最后一个图片;

我们再看当我们的h等于1的时候:

最左边的是我们的开始时候的图片,然后我们插入一个结点,这个结点插入到我们的b结点的右边了,然后这时候因为他不是一个单纯的一边比较高,这时候我们就使用一个左右双旋,我们先使用左旋,再使用一个右旋;

我们看根节点10的左子树,5这棵树的右边比较高,我们就使用一个左旋,然后得到我们的第三个图片,,然后我们再以我们的根节点10作为我们的旋转点,进行一个右旋得到我们的第四个图片;

平衡因子的调节:

当我们进行了左右双旋,其实就是进行了左旋,再进行右旋,我们上期的时候,我们学习了左单旋和右单旋,我们的单旋的代码最后,我们会把parent和subL的平衡因子置为0;

但是我们的双旋之后,我们的parent和subL的平衡因子不一定是0;这时候,我们就要主动的去改变他的平衡因子,这就要分为几种情况了;

我们看这个图片:我们给5结点的右子树插上一个结点,这时候我们给5结点进行左旋,这时候要把b子树给拆开来看,不然的话,不能达到我们的左旋的逻辑;

这个时候,我们就要分情况来进行讨论了。

第一种:

我们把b子树拆开,把高度为h的树分成一个结点和两个高度为h-1的树,然后在e树上插入一个结点,e树的高度变回h,然后我们进行左右双旋,得到最后一个图片的树。

第二种:

我们给f子树插入结点;然后,,,最后得到我们的第三个数;

第三种:

当我们的h等于0的情况;

这三种情况最后得到的树,里面的平衡因子都是不同的,需要我们手动的按照结果去修改;

理解:

当我们的平衡因子出现问题,我们需要进行旋转,我们先看我们的比较高的子树,这个图片里面就是我们的左子树,左子树的右边子树比较冗余,我们就在左子树上进行一个左旋,完后整棵树的左边的数据比较冗余,我们这时候就给整棵树进行一个右旋。

我们看我们的左右双旋的抽象图,我们的左右双旋就是要把8那个结点作为我们的调节完后的根节点,然后8的左子树变成我们的5的右子树,8的右子树变成我们的10的左子树。

然后5结点变成我们的8的左节点,10结点作为我们8的右节点;

左右双旋的代码的实现:

我们的左右双旋对我们的左单旋和右单旋实行了复用,我们看代码实现,我们判断他是在哪个树插入的,我们就看8结点的平衡因子;8结点的平衡因子是1的时候,就是f子树的插入,8结点的平衡因子是-1的时候,就是e子树的插入,当然只会是这两个树,如果是a树的话,那就不是左右双旋了;

右左双旋:

这个是我们的右左双旋的抽象图:

我们给我们的b子树插入一个结点,然后这时候我们的10结点的平衡因子变成了2,这时候我们就要进行旋转调整;

我们看我们的总的树的右子树,右子树的左子树数据比较冗余,我们给右子树来一个右旋,然后结束后,总的这棵树右边的数据比较冗余,这时候我们就给整棵树一个来一个左旋。

平衡因子:

右左双旋和左右双旋是比较类似的,平衡因子的调节也是要分为三种情况的,我们要把b子树拆开,然后分成三种情况;,,,最后再根据调整完后的树来修改我们的平衡因子;

第一种:

这个就是我们的其中的一种,我们插入的结点在f树上。我们实现完后手动的修改我们的平衡因子;

第二种:

这次我们插入结点的位置在f树上。

第三种:

这个是我们的第三种h为0的时候的情况;

我们的这三种情况最后的树里面的parent,subL,subR这三个结点的平衡因子都不一样;

实现的时候我们就要分情况手动的修改他。

理解:

我们的右左双旋要把12结点作为我们的根节点,12的左子树作为10的右子树,12的右子树作为15的左子树,然后10作为12的左结点,15作为12的右节点;

右左双旋的代码的实现:

右左双旋和左右双旋都是我们的单旋的复用。

AVL树的查找:

我们输入一个key,当然我们也可以是输入一对数据,然后我们进行查找,找到的话就返回这个位置的指针,没找到就返回空指针。

AVL树的删除:

AVL树的删除,当我们删除一个结点的时候,我们就让这个结点的父亲指向我们的这个结点的孩子,然后把这个结点删除,这个结点删除以后,我们要更新我们的平衡因子,我们看第一个图片,当我们要删除7结点的时候,我们让6结点指向我们的7结点的孩子结点,然后修改6结点的平衡因子,我们的6结点的平衡因子,从0变成了-1,这时候,我们可以停止更新我们的平衡因子了,因为没有什么改变,我们的二叉树的高度没有发生变化。我们的6结点有两个孩子,删除一个后高度没有变化,所以,当我们的平衡因子由0变成1或者是-1的时候,这时候我们就可以停止更新我们的平衡因子了,但是如果是1或者-1变成了0,这时候我们就要再不断地更新平衡因子;

看右边的二叉树,我们删除14的结点以后,8结点的平衡因子变成-2,这时候这个二叉树就要旋转。左右双旋。

相关文章:

  • 性能优化实践:渲染性能优化
  • Python|Pyppeteer实现自动登录小红书(32)
  • 蓝桥杯15届国赛 合法密码
  • 基于 ESP32 和 GC9D01 0.71寸TFT屏幕的逼真眼睛与写轮眼动态显示
  • 2025年- H26-Lc134- 226. 翻转二叉树(树)---java版
  • 《AI大模型应知应会100篇》第48篇:构建企业级大模型应用的架构设计
  • STM32教程:ADC原理及程序(基于STM32F103C8T6最小系统板标准库开发)*详细教程*
  • 01背包专题4:小A点菜
  • Q_OBJECT宏的作用
  • 深度学习中保存最优模型的实践与探索:以食物图像分类为例
  • 【nlohmann\json.hpp】‘_snprintf‘: is not a member of ‘std‘
  • Uni-app 组件使用
  • Git 远程操作
  • 二叉搜索树的最近祖先(递归遍历)
  • 《工业社会的诞生》章节
  • 信息系统监理师第二版教材模拟题第二组(含解析)
  • 【锂电池剩余寿命预测】RF随机森林锂电池剩余寿命预测(Pytorch完整源码和数据)
  • 移动 Trae 目录到 E 盘 - 解决 C 盘空间不足问题
  • 身份认证、访问控制技术、SSO单点登录技术、特权访问管理、身份治理与管理——数据安全守护者
  • 智能合约部署之全国职业院校技能大赛“区块链技术应用”赛项—“航班延误险案例”
  • AI世界的年轻人|横跨教育与产业,他说攻克前沿问题是研究者的使命
  • 辛涛任山东第一医科大学副校长,曾为“博士服务团”成员
  • 五大白酒去年净利超1500亿元:贵州茅台862亿领跑,洋河营收净利齐降
  • 央行就《关于规范供应链金融业务引导供应链信息服务机构更好服务中小企业融资有关事宜的通知》答问
  • 证监会副主席王建军被查
  • 白玉兰奖征片综述丨国产剧集创作的此消彼长