重温数据结构:理解 B 树、B+ 树特点及使用场景

B 树如何保证平衡

我们知道,平衡的树之所以能够加快查找速度,是因为在添加、删除的时候做了某些操作以保证平衡。

平衡二叉树的平衡条件是:左右子树的高度差不大于 1;而 B 树的平衡条件则有三点:

  1. 叶子节点都在同一层
  2. 每个节点的关键字数为子树个数减一(子树个数 k 介于树的阶 M 和它的二分之一
  3. 子树的关键字保证左小右大的顺序

也就是说,一棵 3 阶的 B 树(即节点最多有三个子树),每个节点的关键字数最少为 1,最多为 2,如果要添加数据的子树的关键字数已经是最多,就需要拆分节点,调整树的结构。

网上找到一张很不错的动图,我们来根据它分析下 B 树添加元素时如何保证平衡。

这个图用以表示往 4 阶 B 树中依次插入下面这组数据的过程:

6 10 4 14 5 11 15 3 2 12 1 7 8 8 6 3 6 21 5 15 15 6 32 23 45 65 7 8 6 5 4

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

建议放大图查看

由于我比较懒,我们来根据前几步分析下 B 树的添加流程:

  1. 首先明确:4 阶 B 树表示每个节点最多有 4 个子树、3 个关键字,最少有 2 个子树、一个关键字
  2. 添加 6,第一个节点,没什么好说的
  3. 添加 10,根节点最多能放三个关键字,按顺序添到根节点中
  4. 添加 4,还能放到根节点中
  5. 添加 14,这时超出了关键字最大限制,需要把 14 添加为子树,同时为了保证“所有叶子节点在同一层”,就需要拆几个关键字作为子树:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传 拆为:外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这个拆的过程比较复杂,首先要确定根节点保留几个关键字,由于**“非叶子节点的根节点至少有 2 棵子树”的限制,那就至少需要两个关键字分出去,又因为“子树数是关键字数+1”**,如果根节点有两个关键字,就得有三个子树,无法满足,所以只好把除 6 以外的三个关键字都拆为子树。

谁和谁在一个子树上呢,根据**“左子树比关键字小、右子树比关键字大”**的规律,4 在左子树,10 和 14 在右子树。

继续添加 :

  1. 添加 5,放到 4 所在的子树上
  2. 添加 11,放在 10 和 14 所在的右子树上
  3. 添加 15,按大小应该放到 10、11 和 14 所在的子树上,但因为超过了关键字数限制,又得拆分

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

因为**“根节点必须都在同一层”**,因此我们不能给现有的左右子树添加子树,只能添加给 6 了;但是如果 6 有三个子树,就必须得有 2 个关键字,提升谁做关键字好呢,这得看谁做 6 中间的子树,因为右子树的所有关键字都得比父节点的关键字大,所以这个提升的关键字只能比未来右子树中的关键字都小,那就只有 10 和 11 可以考虑了。

提升 10 吧,没有比它小的做子树,那就只能提升 11 了:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

再添加元素也是类似的逻辑:

  1. 首先考虑要插入的子树是否已经超出了关键字数的限制
  2. 超出的话,如果要插入的位置是叶子节点,就只能拆一个关键字添加到要插入位置的父节点
  3. 如果非叶子节点,就得从其他子树拆子树给新插入的元素做孩子

删除也是一样的,要考虑删除孩子后,父节点是否还满足子树 k 介于 M/2 和 M 的条件,不满足就得从别的节点拆子树甚至修改相关子树结构来保持平衡。

总之添加、删除的过程很复杂,要考虑的条件很多,具体实现就不细追究了,这里我们有个基本认识即可。

正是这个复杂的保持平衡操作,使得平衡后的 B 树能够发挥出磁盘中快速查找的作用。

使用场景

这部分摘自:浅谈算法和数据结构:平衡查找树之B树

文件系统和数据库系统中常用的B/B+ 树,他通过对每个节点存储个数的扩展,使得对连续的数据能够进行较快的定位和访问,能够有效减少查找时间,提高存储的空间局部性从而减少IO操作。他广泛用于文件系统及数据库中,如:

  • Windows:HPFS 文件系统

  • Mac:HFS,HFS+ 文件系统

  • Linux:ResiserFS,XFS,Ext3FS,JFS 文件系统

  • 数据库:ORACLE,MYSQL,SQLSERVER 等中

  • 数据库:ORACLE,MYSQL,SQLSERVER 等中

B+ 树

这部分主要学习自“程序员小灰”的 漫画:什么是B+树?

了解了 B 树后再来了解下它的变形版:B+ 树,它比 B 树的查询性能更高。

一棵 B+ 树需要满足以下条件:

  1. 节点的子树数和关键字数相同(B 树是关键字数比子树数少一)
  2. 节点的关键字表示的是子树中的最大数,在子树中同样含有这个数据
  3. 叶子节点包含了全部数据,同时符合左小右大的顺序

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

简单概括下 B+ 树的三个特点:

  1. 关键字数和子树相同
  2. 非叶子节点仅用作索引,它的关键字和子节点有重复元素
  3. 叶子节点用指针连在一起

首先第一点不用特别介绍了,在 B 树中,节点的关键字用于在查询时确定查询区间,因此关键字数比子树数少一;而在 B+ 树中,节点的关键字代表子树的最大值,因此关键字数等于子树数。

第二点,除叶子节点外的所有节点的关键字,都在它的下一级子树中同样存在,最后所有数据都存储在叶子节点中。

根节点的最大关键字其实就表示整个 B+ 树的最大元素。

第三点,叶子节点包含了全部的数据,并且按顺序排列,B+ 树使用一个链表将它们排列起来,这样在查询时效率更快。

由于 B+ 树的中间节点不含有实际数据,只有子树的最大数据和子树指针,因此磁盘页中可以容纳更多节点元素,也就是说同样数据情况下,B+ 树会 B 树更加“矮胖”,因此查询效率更快。

B+ 树的查找必会查到叶子节点,更加稳定。

有时候需要查询某个范围内的数据,由于 B+ 树的叶子节点是一个有序链表,只需在叶子节点上遍历即可,不用像 B 树那样挨个中序遍历比较大小。

B+ 树的三个优点:

  1. 层级更低,IO 次数更少
  2. 每次都需要查询到叶子节点,查询性能稳定
  3. 叶子节点形成有序链表,范围查询方便
    自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

最后

其实Android开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。

上面分享的腾讯、头条、阿里、美团、字节跳动等公司2019-2021年的高频面试题,博主还把这些技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,上面只是以图片的形式给大家展示一部分。

【Android思维脑图(技能树)】

知识不体系?这里还有整理出来的Android进阶学习的思维脑图,给大家参考一个方向。

【Android高级架构视频学习资源】

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!

…(img-ngKFFnub-1712220281287)]

【Android高级架构视频学习资源】

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!
  • 14
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值