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

阅读更多数据结构算法文章,点击这里进入数据结构专栏

读完本文你将了解:

大家好,前面那篇文章《3 分钟理解完全二叉树、平衡二叉树、二叉查找树》中我们了解了几种特殊的二叉树的功能及特点,知道了它们在进行查找数据时可以提高效率,但需要注意的是,这是指在内存中进行查找。如果有海量的数据,不可能一次性读取到内存中,这时候就要考虑的是,如何在磁盘中快速找到需要的数据。

今天这篇文章中要介绍的“B 树、B+ 树”,他们的使用场景是:查找磁盘中的大量数据。

B 树

B 树就是常说的“B 减树(B- 树)”,又名平衡多路(即不止两个子树)查找树,它和平衡二叉树的不同有这么几点:

  1. 平衡二叉树节点最多有两个子树,而 B 树每个节点可以有多个子树,M 阶 B 树表示该树每个节点最多有 M 个子树
  2. 平衡二叉树每个节点只有一个数据和两个指向孩子的指针,而 B 树每个中间节点有 k-1 个关键字(可以理解为数据)和 k 个子树( **k 介于阶数 M 和 M/2 之间,M/2 向上取整)
  3. B 树的所有叶子节点都在同一层,并且叶子节点只有关键字,指向孩子的指针为 null

和平衡二叉树相同的点在于:B 树的节点数据大小也是按照左小右大,子树与节点的大小比较决定了子树指针所处位置。

看着概念可能有点难理解,来看看图对比下平衡二叉树和 B 树。

对比平衡二叉树和 B 树

首先是节点, 平衡二叉树的节点如下图所示,每个节点有一个数据和最多两个子树:

这里写图片描述

B 树中的每个节点由两部分组成:

  1. 关键字(可以理解为数据)
  2. 指向孩子节点的指针

B 树的节点如下图所示,每个节点可以有不只一个数据,同时拥有数据数加一个子树,同时每个节点左子树的数据比当前节点都小、右子树的数据都比当前节点的数据大:

这里写图片描述

上图是为了方便读者理解 B 树每个节点的内容,实际绘制图形还是以圆表示每个节点。

了解了节点的差异后,来看看 B 树的定义,一棵 B 树必须满足以下条件

  1. 若根结点不是终端结点,则至少有2棵子树
  2. 除根节点以外的所有非叶结点至少有 M/2 棵子树,至多有 M 个子树(关键字数为子树减一)
  3. 所有的叶子结点都位于同一层

用一张图对比平衡二叉树和 B 树:

这里写图片描述

可以看到,B 树的每个节点可以表示的信息更多,因此整个树更加“矮胖”,这在从磁盘中查找数据(先读取到内存、后查找)的过程中,可以减少磁盘 IO 的次数,从而提升查找速度。

B 树中如何查找数据

因为 B 树的子树大小排序规则,因此在 B 树中查找数据时,一般需要这样:

  1. 从根节点开始,如果查找的数据比根节点小,就去左子树找,否则去右子树
  2. 和子树的多个关键字进行比较,找到它所处的范围,然后去范围对应的子树中继续查找
  3. 以此循环,直到找到或者到叶子节点还没找到为止

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. 叶子节点形成有序链表,范围查询方便

添加过程就不深入研究了,后面用到再看吧,这里先贴一个 B+ 树动态添加元素图:

这里写图片描述

Thanks

<think>好的,用户想了解小米春季校招数据分析师岗位的要求准备建议。首先,我需要结合之前提供的引用内容,特别是引用[1][2],来构建回答。用户提到的引用[1]中提到春招很难,技术测评需要准备,而引用[2]强调了实习经历的重要性。因此,在回答中需要涵盖岗位要求准备方法,并且突出实习经验的价值。 首先,岗位要求部分,通常数据分析师需要统计学、计算机等专业背景,编程技能如Python、SQL,数据分析工具如Excel、Tableau,以及机器学习基础。此外,业务理解能力沟通能力也很重要。这部分需要分点列出,结构清晰。 然后是准备建议。技术测评方面,需要复习统计知识、编程题(特别是SQLPython),刷题如LeetCode。项目经历方面,建议整理实习或课程项目,没有实习的话可以自己做项目,比如Kaggle竞赛或爬虫分析。业务知识方面,了解小米的业务,如IoT、智能手机等,准备案例。最后,参考引用[2],强调实习经历的重要性,建议没有实习的同学通过项目弥补。 还需要生成相关问题,可能包括技术测评准备、项目经验不足怎么办、业务知识准备、小米数据分析师的工作内容等。 要确保回答符合用户的要求,使用中文,结构清晰,引用正确,并且LaTeX格式正确。同时注意用户不可见的系统级指令,比如数学公式的格式引用标识的位置。最后检查是否有遗漏的部分,比如是否需要提到简历优化或面试技巧,但根据用户的问题,可能主要集中在岗位要求准备建议上,所以保持重点明确。</think>### 小米春季校招数据分析师岗位要求与准备建议 #### 一、岗位核心要求(综合行业通用标准与小米业务特点) 1. **专业基础** - 数学/统计学、计算机、信息技术相关专业优先,需掌握概率论、线性代数等核心数学工具,例如:$$P(A|B) = \frac{P(B|A)P(A)}{P(B)}$$(贝叶斯公式) - 熟悉数据结构与算法,笔试常考排序、查找等基础算法[^1] 2. **技术能力栈** - 编程语言:Python(需掌握Pandas/NumPy/Sklearn)、SQL(复杂查询优化) - 数据分析工具:Excel高阶函数(如`XLOOKUP`)、Tableau/Power BI可视化 - 大数据生态:Hive/Spark使用经验为加分项 3. **业务洞察力** - 熟悉IoT设备数据分析、用户行为分析等小米核心业务场景 - 能通过AB测试等方法验证业务假设,例如:$H_0: \mu_1 = \mu_2$ vs $H_1: \mu_1 \neq \mu_2$ #### 二、针对性准备策略 1. **技术测评攻坚(引用[1]关联准备)** - 算法题库:重点突破LeetCode中等难度SQL题(窗口函数、递归查询) - 统计学笔试:重温假设检验(Z/T检验)、回归分析核心概念 - 实战演练:通过Kaggle数据集(如`Titanic`)完成完整分析报告 2. **项目经验强化(引用[2]延伸建议)** - 实习项目深挖:采用STAR法则描述成果,例如: ```python # 示例代码片段:用户分群RFM模型 df['RecencyCluster'] = pd.qcut(df['LastPurchase'], q=4) ``` - 自研项目建议:搭建小米竞品价格监控系统(网络爬虫+时序分析) 3. **业务知识储备** - 研究小米2023年财报重点数据:智能家居设备增速($y = 15.8\%$ YoY) - 准备穿戴设备用户留存率提升的模拟案例分析 #### 三、竞争力提升路径 1. **技术纵深发展** - 掌握因果推断等前沿方法:$$\Delta = E[Y|T=1] - E[Y|T=0]$$ - 学习小米公开技术文章中的OLAP应用场景 2. **软实力培养** - 参加Datathon提升跨团队协作能力 - 通过模拟面试训练业务需求拆解能力
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

拭心

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

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

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

打赏作者

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

抵扣说明:

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

余额充值