一、B-Tree 概述
1、B树(B-tree)是一种自平衡的树形数据结构,通常用于数据库和文件系统中。它被设计用来存储大量数据并允许有效地进行插入、删除和查找操作。
-
支持高效的插入、删除和查找操作: B树通过自平衡的方式,确保每次操作的时间复杂度保持在对数级别,即O(log n),这使得对大量数据的插入、删除和查找操作都非常高效。
-
适合大规模数据存储: B树能够有效地处理大量数据,因为每个节点可以存储多个子节点,使得整棵树能够存储大量的有序数据。
-
顺序访问优化: B树的节点通常按顺序存储,这使得范围查询和顺序访问非常高效,适合于需要频繁进行这类操作的应用场景。
-
用于数据库和文件系统中的索引: 在关系型数据库管理系统(RDBMS)和文件系统中,B树常被用作索引结构,用来加速数据的检索。它能够快速定位数据,支持快速的查询操作。
-
适合于外部存储的应用: 由于B树的节点大小适中,能够有效地利用磁盘或其他外部存储设备的缓存,因此在需要持久化存储大数据集合的应用中,B树也是一个常见的选择。
二、B-Tree 特性
-
阶数:B 树的阶数(m)定义了每个节点的最大子节点数量;每个节点最多可以有 m 个子节点,最少可以有 [m/2] 个子节点(除根节点外)。
-
根节点:若根节点不是叶子节点,则至少有两个子节点。
-
子节点:除了根节点和叶子节点外,每个非根非叶子节点至少有ceil(m/2)个子节点。
-
所有叶子节点在同一层:B 树是一种高度平衡的树,所有叶子节点都在同一层,确保查找操作的时间复杂度为 O(log n)。
-
关键字的数量:每个节点最多可以有 m-1 个关键字;每个节点(除根节点外)至少有 [ceil(m/2)-1] 个关键字。
-
分裂和合并:当插入一个键导致某个节点的键数量超过 m-1 时,节点会进行分裂;分裂是将中间键提升到父节点,并将节点分成两个子节点;当删除一个键导致某个节点的键数量少于 [ceil(m/2)-1] 时,节点可能会与相邻的兄弟节点合并,或从兄弟节点借键。
-
查找、插入和删除:查找操作从根节点开始,逐层线下查找,直到找到目标键或到达叶子节点;插入操作在叶子节点插入新键,并根据需要进行分裂;删除操作在叶子节点删除目标键,并根据需要进行合并或键借用。
总结:
1.每个子节点最少有 ceil(m/2) 个子节点,最多有 m 个子节点。
2.每个节点(除根节点外)最少有 [ceil(m/2)-1] 个关键字,最多有 m-1 个关键字。
3.当进行插入或删除操作后,如果不符合 B 树结构,会进行分裂或者合并与借键操作,来调整和维护树的结构。
ps:
1.ceil(m/2):ceil = ceiling 向上取整,例:ceil(5/2) = 3
2.根节点:位于树的最上方,是树的起始节点。
3.子节点:也叫做 “内部节点”,根节点下面的节点,它们既有父节点也有子节点。
4.叶子节点:树的最底层节点,没有子节点。
三、插入操作
一、以 5 阶 B 树为例,关键字的数量:[ceil(m/2)-1] <= n <= m-1。计算后为:2 <= n <= 4, 当 n > 4 时,中间键提升到父节点,并将节点分成两个子节点。
![](https://i-blog.csdnimg.cn/direct/b5e8088c2af3447f9c360dd4bfbf997c.png)
2、插入 H。
2.2、关键字数量大于 4 了(n > 4),这时中间的节点需要向上分裂到新节点,两边节点分裂。
3、插入 E K Q。
4、插入 M。
4.2、关键字数量大于 4 了(n > 4),中间元素 M 向上分裂到父节点,两边节点分裂。
5、插入 F W L T。
6、插入 Z。
6.2、中间元素向上分裂到父节点。
7、插入 D。
7.2、中间元素向上分裂。
8、插入 P R X Y。
9、插入 S。
9.2、中间元素向上分裂
9.3、根节点关键字数量大于 4 ,继续向上分裂到新节点。规则参考 B-Tree 特性第 5 条。
二、补充:依次将关键字 5、6、9、13、8、2、12、15 插入初始为空的 4 阶 B 树。
4 阶 B 树,关键字的数量:[ceil(m/2)-1] <= n <= m-1。计算后为:1 <= n <= 3。
当 n > 3 时,中间键提升到父节点,并将节点分成两个子节点。
1、先插入 5、6、9。
2、插入 13。
2.1、这时选择 6 或 9 都可以,选择 6 叫做向下取整,选择 9 叫做向上取整。下列所有图右侧都为向上取整。
3、插入 8。
4、插入 2。
5、插入 12。
6、插入 15。
四、删除操作
一、
1、规则:
2、栗子:
2.2、如果删除 9 ,那么 8 就是前驱,12 就是后继。
二、
1、原数据:
2、删除 21。
2.2、删除后,叶子节点关键字满足下限,大于等于2,不做处理。
3、删除 27。
3.2、使用前驱 26 或者后继 28 进行替换。下图使用前驱进行替换。
4、删除 32。
4.2、删除 32 后,低于下限,找左右兄弟借键,只有左兄弟,但左兄弟刚好处于下限,借不了,只能进行合并操作。
4.3、当前节点满足上限与下限,不再做操作。
5、删除 40。
5.2、删除后,有左右兄弟,但是都无法借键。这时我们选择跟左兄弟进行合并(也可以选择右兄弟)。
5.3、合并完成后,子节点关键字 41 不满足下限,这时左兄弟 22 和 26 也不够借,进行合并操作。