B+树的原理图解

B+树是B树的变体,也是广泛应用于数据库和文件系统中的一种自平衡的树形数据结构。与B树不同的是,B+树所有的键值都保存在叶子节点中,内部节点仅作为索引使用。这种结构使得B+树在查找、范围查询等操作中比B树更加高效。

一、基本性质

  • 叶子节点存储所有数据 :B+树中的所有实际数据(键值对)都保存在叶子节点中,内部节点只存储索引键值,用来引导查找过程。

  • 内部节点仅存储索引 :与B树不同,B+树的内部节点只存储键值而不存储数据记录,用于引导查找路径。每个内部节点保存k个索引键值和k+1个子树指针。

  • 叶子节点链表:所有叶子节点通过一个链表相互连接。这样可以方便地进行范围查询或顺序访问。

  • 树的高度平衡:B+树与B树一样,是一棵平衡树。所有的叶子节点都处于同一层,保证树的高度稳定,进而保证查询的效率。

  • 键值数量限制

    • 每个内部节点可以存储 ⌈m/2⌉ - 1m-1 个键值,m 是B+树的阶数。
    • 每个叶子节点至少存储 ⌈m/2⌉m 个键值。

二、查找

查找过程描述
  • 从根节点开始:从根节点出发,根据索引键值范围,选择合适的子树继续查找。

  • 递归向下:在每层的内部节点中,通过比对键值范围,选择相应的子树指针继续向下查找,直到叶子节点。

  • 叶子节点查找:在叶子节点中找到目标键值,查找成功。如果叶子节点中没有找到,则查找失败。

示例

在上述的B+树中查找55,路径便是如下图所示

三、插入

插入过程描述
  • 找到插入位置:从根节点开始,沿索引节点的路径找到合适的叶子节点。

  • 插入叶子节点

    • 如果叶子节点未满(即键值数量少于 m),则将新键值直接插入该叶子节点,并保持键值的顺序。

    • 如果叶子节点已满,则需要对叶子节点进行分裂。

  • 叶子节点分裂

    • 如果叶子节点满了,分裂成两个节点。

    • 将中间键值提升到父节点作为索引键值,父节点指向新分裂出的两个叶子节点。

  • 父节点更新:如果父节点因分裂而满,则继续对父节点进行分裂,直到根节点。若根节点分裂,树的高度增加一层。

示例

下面的B+树分别插入值

{49,48,52,99}

先插入49,直接插入在叶子结点,没有什么问题

再插入48

可以看出,此时节点需要分裂了

分裂完的上层节点需要接着分裂

再插入一个99,由于99比85都大,所以需要更新索引

四、删除

删除过程描述
  • 找到要删除的键值:从根节点出发,沿索引路径找到包含目标键值的叶子节点。

  • 删除叶子节点中的键

    • 如果删除的键值后,叶子节点仍满足最小键值要求(至少 ⌈m/2⌉ 个键),则直接删除键值。
    • 如果删除后键值数量不足,则需要借用或合并节点。
  • 借用兄弟节点的键值:如果兄弟节点有多余的键值,可以从兄弟节点借用一个键值,以保证当前节点的键值数量符合要求。

  • 合并节点:如果兄弟节点也没有多余键值可借用,则需要将当前节点与兄弟节点合并,并调整父节点中的索引。

  • 父节点调整:如果父节点因合并而减少了索引键值,可能需要进一步调整父节点,甚至导致根节点被删除。

示例

删除以下数据

{85,40}

首先删除85,85删除后叶子节点也满足要求,所以可以直接删除

再删除40,此时可以看前后的兄弟节点,发现无法借,所以需要合并操作

和兄弟节点进行合并

此时50的节点也无法满足要求,也需要与兄弟节点合并

五、B+树的优缺点

优点:
  1. 高效的范围查询
    B+树的叶子节点通过链表相连,可以实现快速的顺序遍历和范围查询,非常适合数据库中查询某一范围内的数据。
  2. 更高效的磁盘访问
    B+树的内部节点只存储索引,叶子节点存储实际数据,这种结构减少了磁盘I/O访问次数,使得B+树在存储和检索时更加高效。
  3. 稳定的查询时间复杂度
    B+树的高度始终保持较低,查找、插入、删除操作的时间复杂度均为O(log_m(n)),非常适合大规模数据场景。
缺点:
  1. 实现复杂度高
    B+树的插入和删除操作需要频繁地调整索引和叶子节点的结构,代码实现相对复杂。
  2. 占用空间稍大
    虽然B+树的叶子节点通过链表相连,方便范围查询,但这种链表结构需要额外的指针,增加了空间开销。
相关推荐
搬砖的小码农_Sky3 小时前
C语言:数组
c语言·数据结构
先鱼鲨生4 小时前
数据结构——栈、队列
数据结构
一念之坤4 小时前
零基础学Python之数据结构 -- 01篇
数据结构·python
IT 青年5 小时前
数据结构 (1)基本概念和术语
数据结构·算法
熬夜学编程的小王5 小时前
【初阶数据结构篇】双向链表的实现(赋源码)
数据结构·c++·链表·双向链表
liujjjiyun6 小时前
小R的随机播放顺序
数据结构·c++·算法
Reese_Cool7 小时前
【数据结构与算法】排序
java·c语言·开发语言·数据结构·c++·算法·排序算法
djk88888 小时前
.net将List<实体1>的数据转到List<实体2>
数据结构·list·.net
搬砖的小码农_Sky8 小时前
C语言:结构体
c语言·数据结构
_OLi_10 小时前
力扣 LeetCode 106. 从中序与后序遍历序列构造二叉树(Day9:二叉树)
数据结构·算法·leetcode