B树 B+树 B*树

来源:互联网 发布:软件培训内容 编辑:程序博客网 时间:2024/06/05 06:06
1 B 树:
一棵m阶的B树,约束条件如下:
a 树中一个节点最多有m棵子树,这也是m阶的含义。
b 若根节点有孩子,至少有两棵子树。
c 除根节点之外的所有非叶子节点至少有[m/2](上界) 棵子树。
d 所有的非终端节点包括的信息有:
n(该节点含有的关键字数目),索引指针A0,关键字K1,索引指针A1,关键字K2...,关键字Kn,索引指针An
也就是说有n个关键字,会有n+1个索引指针,指向其孩子节点。并且,A0所指的孩子节点的关键字均小于K1,A1所指的孩子节点关键字均大于K1
显然n的范围: [m/2]到m-1的闭区间。
e 所有的叶子节点都出现在同一层次上,并且不带信息。即叶子节点不存关键字,是查找失败的节点,实际上不存在,只是一个虚拟的概念。


从上述定义可以看到,实际上B树只有非叶子节点才存储数据,并且,一个非叶子节点,含有的关键字数目的范围限制在[m/2]到m-1的闭区间,因为子树的范围是关键字数目+1。一个非叶节点,如果有K个关键字,那么就会有k+1棵子树。


在B树中查找一个关键字的过程:

可以看出,B树是一个多路的搜索树,查找过程与二叉搜索树类似。而且B树是一个完全平衡的树,所有的叶子节点都是在最后一层。


插入一个节点:
首先通过搜索找到这个节点被插入的位置,即一个虚拟的叶子节点所属的非终端节点。然后将节点加入到该非终端节点中。如果这个非终端节点关键字的数目超过了m-1,需要将该节点分裂为两个。分裂的时候要考虑父节点能够容纳的子节点数目,分裂导致超过了父节点容纳的子节点数,同样也需要对父节点进行分裂。

删除一个节点:
同样,通过搜索找到该节点,并从中删除。假设删除了非终端节点中的Ki,则Ai指向大于Ki的子树,显然Ai指向子树中的最小关键字Y可以代替要删除的Ki,最后删除Y即可。

如果该节点为最下层的非终端节点,并且其中的关键字数目不少于[m/2](上界),则删除完成。否则需要进行合并。


对B树的维护是合并与分裂操作,使得B树在查找时有较好的性能。


2 B+树:

一棵m阶的B+树,约束条件如下:
a 树中一个节点最多有m棵子树,这也是m阶的含义。
b 若根节点有孩子,至少有两棵子树。
c 除根节点之外的所有非叶子节点至少有[m/2](上界) 棵子树。
d 一个节点如果有n个子树,也有相应的n个关键字。 所有的非终端节点只是索引,仅包含其子树最大关键字。
e 所有的叶子节点中包含了全部的关键字信息,以及指向含这些关键字记录的指针。并且叶子节点本身依照关键字从小到大进行排序。

对于非叶节点来说,含有关键字数目范围在: [m/2]到m的闭区间。B+树中所有的叶子节点都连在一起。

B+树中查找的过程:
一般B+树中有两个指针,一个指向根节点,这样可以进行随机查找;一个指关键字最小的叶子节点;这样可以进行顺序查找。
在B+树中进行随机查找,与B-树类似,由于父节点总是存储子节点关键字的最大值,我们可以很容易通过父节点找到相应的子节点,最终找到叶子节点。由于数据其实在叶子节点中,叶子节点包含的数据往往比较多,我们需要对叶子节点进行顺序搜索,叶子节点内部是有序的,可以进行二分搜索。

B+树的插入:
B+树的插入仅在叶子节点上进行。当叶子节点中的关键字数目大于m时,要分裂成两个节点,并且双亲节点中也应包含这两个节点中的最大关键字。
B+树的删除:
删除同样也在叶子节点中进行。删除后,叶子节点中的关键字数目小于[m/2]时,要进行合并。

3 B*树:

在B+树基础之上再加上指向兄弟节点的指针,这样在分裂和合并的时候也考虑到了兄弟节点,使得数据更加集中。

4 B树与B+树区别:

可以看到B+树内节点含有关键字的数目比B树多1.而且,内节点不包含实际数据,存储内节点的代价比较小。B+树的非叶子节点只是起到了索引所用。那么,相对于B树只需要读取少量的盘块数,就可以获得实际查找数据所在的位置信息。而且B+树可以支持range查找,适应于数据库的需求。如果最终数据很大,在磁盘上时,使用B+树要比B树好。





原创粉丝点击