B+Tree介绍

本文深入探讨B+树的结构及工作原理,包括插入与删除操作的详细步骤,并对比B树的特点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

BTree BTree是一种多路搜索树,每个节点都包含一系列键和指针,最小的BTree节点包含4个键和5个指针。BTree中只有数据节点。

BTree是动态的。当添加或删除数据时,BTree的高度会随之增加或减少。

B+Tree B+Tree包含数据节点和索引节点。数据节点通常就是B+Tree的叶子节点(注:叶子节点指树最底层的节点,它没有子节点);而索引节点则通常是根节点或中间节点。

在添加或删除数据时,B+Tree会调整索引节点,因此,类似于BTree,B+Tree的高度也会动态地增加或减少。索引节点的内容和数量可以反映出这种变化。

B+Tree和BTree使用“填充系数(fill factor)”来判断节点是否需要重组,在所有B+Tree和BTree中,最小的填充系数是50%。本文使用了最小的节点结构,范例中的B+Tree符合如下规范:

每节点含键数 4
每节点含指针数 5
填充系数 50%
每节点最少含键数 2

上表展示了每节点至少需要包含两个键,根节点可以除外。

下图是一个B+Tree,它的索引节点还未填满(根节点含有一个未使用的键空间)。另外,在第二个叶子节点上也有未使用的空间。

4键B+Tree
点击查看原图

向B+Tree添加数据

键的大小决定了数据的保存位置,叶子节点按键的大小排序,相邻两节点上保存着一对互相指向对方的指针。这种指针可以提高增删数据时节点重组的效率。

当我们向B+Tree添加数据时会面临三种情况,每种情况都会导致不同的插入算法,这三种情况为:

B+Tree的插入算法
叶子节点已满 索引节点已满 行为
在相应叶子节点插入数据并排序
1. 相应叶子节点拆分为左节点和右节点
2. 中间键复制到索引节点并排序
3. 键<中间键的数据放到左节点
4. 键>=中间键的数据放到右节点
1. 相应叶子节点拆分为左节点和右节点
2. 键<中间键的数据放到左节点
3. 键>=中间键的数据放到右节点
4. 相应索引节点拆分为左节点和右节点
5. 键<中间键的索引放到左节点
6. 键>中间键的索引放到右节点
7. 中间键移动到上一级索引节点

如果上一级索引节点也满了,继续拆分之

插入算法示例

下面用实例来解释上面三种情况。我们从最简单的情况开始:向未满的叶子节点插入数据。由于只在第二个叶子节点上有未使用空间,该叶子节点包含25和30,现在我们插入数据28。下图展示了插入结果。

插入数据28
点击查看原图

当叶子节点已满而索引节点未满时

现在,我们插入数据70。70被分配给第三个节点,包含50、55、60和65。不幸的是该节点已满,于是它按照如下方式被拆分:

左节点 右节点
50, 55 60, 65, 70

中间键为60,它将被复制到索引结点并排列在50和75之间。

下图展示了插入70之后的结果。

插入数据70
点击查看原图

当叶子节点和索引节点都满时

最后我们插入数据95。95被分配给最后一个节点 ,包含75、80、85和90。由于该节点已满,它将被拆分为两个节点:

左节点 右节点
75, 80 85, 90, 95

中间键为85,将被复制到索引节点。不幸的是,索引节点也满了,所以它也会被拆分:

左节点 中间键 右节点
25, 50 60 75, 85

中间键为60,将被移动到上一层索引页 。下图展示了插入95后的结果:

插入数据95
点击查看原图

节点重组

B+Tree会通过节点重组来降低节点拆分率。当某个叶子节点已满,而与它相邻的节点未满时,便会发生重组。此时该叶子节点不会被拆分,而是将一条数据移动到相邻的叶子节点上,必要时会调整索引节点。通常情况下,左侧的节点(如果存在)会先于右侧的节点被选中。

举个例子,让我们回到向B+Tree插入70之前。前面已经说过70会被插入到包含50、55、60、65的叶子节点。注意该节点已满,但它的左侧节点尚有空间可用。

B+Tree当前状态
点击查看原图

通过节点重组我们将最小的键50移动到左侧节点 。由于50同时出现在索引节点中,所以索引节点也将被调整。重组结果如下图:

插入数据70
点击查看原图

从B+Tree中删除数据

从B+Tree中删除数据时也会面临三种情况,每一种情况导致不同的删除算法,这些情况是:

B+Tree的删除算法
叶子节点饱和度<填充系数 索引节点饱和度<填充系数 行为
从叶子节点中删除数据并重新排列数据。如果被删除数据的键同时出现在索引节点中,使用下一个相邻的键顶上。
将叶子节点和与它相邻的节点合并。同时修改索引节点中的相关键。
1. 将叶子节点和与它相邻的节点合并。
2. 修改索引节点中的相关键。
3. 将索引节点和与它相邻的节点合并。

如此反复,直到当前节点的饱和度>=填充系数或者到达根节点

现在让我们回到向B+Tree插入95之后,回顾一下,当时的B+Tree如下图所示:

B+Tree当前状态
点击查看原图

从B+Tree中删除70

我们先从B+Tree中删除70。70在第四个叶子节点,包含60、65和70。删除70之后,这个节点上还有2条数据,其饱和度为50%=填充系数,我们只需简单地删除70即可。下图展示了删除后的状态:

删除数据70
点击查看原图

从B+Tree中删除25

接着,我们从B+Tree中删除25。25在第二个叶子节点,包含25、28和30。删除25后该节点的饱和度为50%。同时,25出现在索引节点中,因此,25被删除后28需要顶上。

下图展示了删除后的状态:

删除数据25
点击查看原图

从B+Tree中删除60

最后,我们从B+Tree中删除60。这次删除就没那么简单了,原因如下:

1. 包含60和65的叶子节点在60被删之后,饱和度低于填充系数。所以需要合并相邻叶子节点 。

2. 叶子节点合并之后,上一级索引节点会删除一个键,其饱和度也会低于填充系数。所以需要合并相邻索引节点。

3. 60作为根节点中的唯一键,在删除之后,根节点也随之消失。

下图展示了删除60之后的B+Tree。注意只剩余一个索引节点。

删除数据60
点击查看原图

原文地址:http://baze.fri.uni-lj.si/dokumenti/B+%20Trees.pdf

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值