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

map和set的遗留 + AVL树(1):

在讲解新的东西之前,我们把上节遗留的问题说一下:

遗留问题:

首先,我们的最上面的代码是一个隐式类型转换,我们插入了一对数据。

我们说了,我们的方括号的底层是insert,当我们调用operator的[]的时候,这时候他的底层是insert,当我们的map没有这个数据的时候,我们这时候就会把这个数据插入。

但是当我们调用operator[]的时候,我们的map二叉树里面有我们的这个数据的时候,我们的map就会返回我们的val的引用。这时候我们就可以对他进行修改,因为返回的是引用,我们这时候就可以直接的把val进行修改。

我们看我们的最后的代码,我们的[]调用我们的二叉树的key是left的时候,我们的[]的返回值就是我们的val的引用,这时候我们打印的结果就是 “左边”。

[] 总结:

如果[]引用的数据在的话,我们就返回val的引用。如果[]引用的数据不在的话,我们就把这个数据插入到我们的map里面。

我们再看一下我们的multimap:

这个是允许我们的数据冗余的map。

我们看上面的代码:1. key相同val相同的插入。2. key相同val不同的插入。

其实他插入的时候是不看我们的val的,只看我们的key,因为我们的key才是维持我们的二叉树的看点;(我们可以修改我们的val的值,但是不能修改我们的key,因为我们的key是维持我们的二叉树的左小于根小于右的基本结构)。

我们库里面的multimap是没有我们的[]的接口的,没有我们的这个接口,因为当我们使用[]的时候,我们有好几个同名的key,那么这时候返回哪个val的引用呢?所以就没有这个接口;

其他的接口,比如我们的erase,他还是把我们的数据删除,然后给你返回删除了几个。

我们看上面,我们把key传进去,他会把所有的相同的key删除掉。

旧的遗留的问题我们已经讲完了,我们来看今天我们要新学的东西:

AVL树:

我肯看上面的概念:AVL树要求我们的左右子树都是AVL树,并且左右子树的高度差不超过1,我们的AVL树相比较我们的普通的二叉搜索树就有了本质的提升,不会再有那种偏移很大的情况;

我们上面的有一点我们提到“平衡因子”,AVL树的任何的结点里面的平衡因子都是“0,1,-1”,这个不是必须的。但是可以方便我们去观察和控制树是否平衡。

我们看这个图片:我们的搜索二叉树,左边是AVL树,右边是普通的二叉搜索树,不是AVL树。

右边的搜索二叉树的结点(10)的右边的树的高度为2,左边的树的结点的高度为0,这就不满足我们的AVL树的要求了。

AVL树的插入:

我们看我们的AVL树的插入,我们的插入和我们的普通的搜索二叉树一样的方式我们去插入,然后我们插入后更新我们的平衡因子。

我们看我们的上面的第一种的,我们更新完平衡因子后,我们发现我们的平衡因子还是在正常的范围,就结束了。

(平衡因子)更新原则:

(平衡因子)更新的停止条件:

我们看我们的剩下的的两种方式,我们插入结点以后,我们更新我们的parent的平衡因子,我们不断的往上更新(更新的原则我们看上面的概念),最后发现我们的结点的平衡因子超出我们的范围了,这时候我们就要旋转控制平衡。

旋转:

我们的旋转首先当然是要保持好我们的搜索树的规则。我们的搜索树的基本的逻辑不能改变。

让我们的树从不平衡变得平衡,其次要降低我们的树的高度。

右单旋:

右单旋就是我们的左边的树有点高了,我们往右边压一点;

左边的树的高度高了(平衡因子有问题的时候),我们就右单旋。

我们这里的a子树,他是不能自身的产生旋转的,它必须是更新到我们的根节点然后整个二叉树发生旋转。

我们的旋转的核心逻辑就是:把我们的5的右子树给到我们的10的左子树,然后把5结点作为我们的树的新的根节点,10结点引领的树作为我们的5结点的右子树。

我们这里的h我们是抽象的树,我们的树的高度为h,然后我们看几个例子,表示我们的不同的h。

我们这里的a子树,他是不能自身的产生旋转的,它必须是更新到我们的根节点然后整个二叉树发生旋转。

我们的整个第三种情况,我们的a子树必须是x,不能是其他的两种,其他的两种的话他可能是不发生旋转,也可能是直接在a子树里面发生旋转了,我们的要求自身是不能直接进行旋转的,必须要更新到我们的根节点。

随着我们的h的变大,我们的场景次数爆炸式的增长。

但是不管是下面的子树a,b,c子树有多么的复杂,我们还是遵从我们的核心的逻辑就可以。

右单旋的代码的实现:

左单旋:

我们的AVL树的右边的子树的高度比较高(平衡因子有问题)的时候,我们就进行左单旋。

我们来看我们的左单旋,当我们给我们的b子树插入一个结点的时候,这时候我们的15结点的平衡因子就变成-1,然后我们的parent结点的平衡因子就变成-2。这时候我们的右边的子树的高度比较高,这时候我们就使用左旋来解决整个问题。

左旋和右旋非常相似,我们看我们的这个图片,当我们的b子树插入一个新的结点的时候,这时候b子树的高度+1

我们看我们左单旋的核心:我们把subRL作为我们的parent的右节点,然后让parent作为我们的subR的左节点,(我们实现代码的时候,我们不但要实现我们的两个结点直接的连接逻辑,不要忘记我们的结点里面还有一个_parent指针,我们还要把我们的父亲指针指向我们的父节点)。

这个是我们的左单旋的代码的实现;

相关文章:

  • K8S - StatefulSet 与 DaemonSet - 有状态应用部署与节点管理策略
  • [面试]SoC验证工程师面试常见问题(二)
  • PyTorch_创建张量
  • 浅谈SpringBoot框架中的单例bean
  • 【KWDB 创作者计划】利用KWDB解决工业物联网场景中的海量数据管理难题的思考
  • 代码随想录单调栈part2
  • C 语言 第五章 指针(6)
  • 网工_IP协议
  • 【算法基础】冒泡排序算法 - JAVA
  • 【质量管理】现代TRIZ问题识别中的功能分析——组件分析
  • 从零开始讲DDR(9)——AXI 接口MIG 使用(2)
  • 文章五《卷积神经网络(CNN)与图像处理》
  • 第 6 篇:AVL 树与 SB 树:不同维度的平衡探索 (对比项)
  • 【质量管理】现代TRIZ问题识别中的功能分析——相互接触分析
  • 滑动窗口leetcode 209和76
  • PostgreSQL自定义函数
  • 特殊运算符详解:身份运算符、成员运算符与三目运算符
  • Ghost-Downloader-3开源下载软件,使用 Python 构建的跨平台 Fluent-Design AI-boost 多线程下载器
  • 使用mybatis实例类和MySQL表的字段不一致怎么办
  • 文件操作--文件下载读取漏洞
  • 泽连斯基拒绝普京72小时停火提议,坚持应尽快实现30天停火
  • 3:0战胜日本队,中国羽毛球队挺进2025苏迪曼杯决赛
  • 艺术开卷|韩羽读齐白石:妙在似与不似之间
  • 旭辉控股集团:去年收入477.89亿元,长远计划逐步向轻资产业务模式转型
  • 海警巡航时海豚围舰艇嬉戏,专家:证明海域生态环境持续向好
  • 解放日报:让算力像“水电煤”赋能千行百业