B-树、B+树和B*树

一. B-树(B树)

1. 基础知识

m阶-平衡树,一个节点有m个地址域,m-1个数据域,B树的所有叶子节点都在同一层。

B-树除根节点和叶子节点外,其他节点的孩子至少有一半个数的孩子(指针域)(比如说有5个孩子,ceil(5/2)=3,至少有3个孩子)

应用场景:文件索引系统的实现。
在这里插入图片描述

2. 插入操作

  • 如果叶子结点空间足够,即该节点的关键字树小于m-1,则直接插入叶子结点的左边或右边(节点内的元素是有顺序的);
  • 如果空间满了以至没有足够的空间去添加新元素,即该节点的关键字数已经有了m个,则需要将该节点进行“分裂”,将一半数量的关键字元素分裂到新的其相邻右节点中,中间元素上移到父节点中,而且当节点中关键元素向右移动了,相关的指针也需要向右移;
  • 此外,如果在上述中间关键字上移到父节点的过程中,导致根节点空间满了,那么根节点也要进行分裂操作,这样原来的根节点中的中间关键字元素向上移动到新的根节点中,因此导致树的高度增加一层

【例如】 插入以下字符字母到一颗空的5阶B树中:C、N、G、A、H、E、K、Q、M、F、W、L、T、Z、D、P、R、X、Y、S

分析:5阶B树,非根节点关键字个数n满足2<=n<=4,每个节点最多含有5个孩子,出根节点叶子结点外,其他节点至少有两个数据,三个指针域。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
对于B树来说,分裂都是向上分裂的,是非常平衡的。所有的叶子节点都在同一层,且满足搜索树的性质

3. 删除操作

首先查找B树中要删除的元素,若元素存在,则进行删除,删除该元素后,需要判断该元素是否有左右孩子节点

  • 如果有,则上移孩子节点中的相近元素(左孩子中最右边的节点或者右孩子中最左边的节点)到父节点中去。
  • 如果没有,直接删除。

调整操作

删除元素,然后进行元素移动之后,如果节点关键字数目不满足条件(小于ceil(m/2)-1),则需要看其相邻的兄弟节点是否丰满(关键字个数大于ceil(m/2)-1)

  • 如果丰满,则向父节点借一个元素来满足
  • 如果其相邻兄弟都刚脱贫,即借了之后其节点数目小于ceil(m/2)-1,则该节点与其相邻的某一兄弟节点进行“合并”成一个节点,以此来满足条件。

依次删除H、T、R、E
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4. B树的磁盘IO优势和搜索效率

Windows和linux的文件搜索,以及数据库的索引,都用到了B+树结构(修改原始B树结构可得到)

在系统中的数据搜索中:大量的数据都是存储在磁盘上的。为了增加系统的搜索速度,我们一般会给数据创建索引。而所谓的创建索引,就是给数据进行排序,然后进行数据搜索就更加快速。

如果想对磁盘上存储的数据进行快速搜索查找需要解决两个问题:

  • 更少的磁盘I/O
  • 更快的搜索算法

我们在这里采用m阶平衡树(节点分裂调平衡)。红黑树不是平衡树,是二阶非平衡树。

对比AVL树以及B树的效率

操作系统管理内存都是按页面(4K)分配,管理磁盘是按(16K)分配。我们的文件在磁盘存储,从磁盘读1个文件,读4个字节,实际上,操作系统从磁盘是按block(16K)来读取的。

磁盘的最小单位是扇区,一个扇区大小为512字节,一个block是16K,16K除以512就是扇区的个数。

假如现在从磁盘读取10000000个索引,构建索引树,对比B树和AVL树的花费:

  • 如果用AVL树(相当于2阶B树)构建索引树来存储10000000个索引,需要24层。一个节点就是存储着一个索引数据,最差情况就是每个节点的数据都不在一个磁盘block上,一个节点对应一个磁盘I/O,我们查找一个数据最多查找24次,即最多需要24次磁盘I/O。
  • 同理,使用300阶B树,查找一次数据最多找3层,花费3次磁盘I/O。

故在构建索引树的时候,我们更多的使用B树

二. B+树

在这里插入图片描述
在这里插入图片描述

1. m阶B+树和m阶B树的区别

  • B+树的非叶子节点只存数据,不存数据地址
  • 索引项全部出现在叶子节点当中,索引项对应的数据也全部在叶子节点。所以在B+树中搜索每一个数据所花费的磁盘I/O一样,而B树是离根节点越近的搜索越快
  • 把叶子结点,即全部数据串在一条链表中,这条链表是有序的。所以当我们进行区间查找及整表搜索不用遍历这颗复杂的B+树,直接遍历叶子结点即可
  • B+树存储的索引值是有重复的,且每个节点中的关键字是有序的
    在这里插入图片描述

2. B+树比B树更适合操作系统的文件索引和数据库索引的原因

B+树的磁盘读写代价更低,B+树的内部节点没有指向关键字具体信息的指针,因此内部节点相对B树更小。如果把所有同一内部节点的关键字放在同一块磁盘中,盘块盘块所能容纳的关键字数量也就越多,一次性读入内存中的需要查找的关键字也就越多,相对IO读写次数降低。

例如,假设磁盘中的一个盘块容纳16bytes,而一个关键字2bytes,一个关键字具体信息指针2bytes。一颗9阶B-tree(一个节点最多8个关键字)的内部节点需要两个盘块。而B+树内部节点只需要1个盘块。当需要把内部节点读入内存中的时候,B树就比B+树多一个盘块查找时间(在磁盘中就是盘片旋转的时间)

三. B*树

是B+树的变体,在B+树的非根节点和非叶子节点再增加指向兄弟节点的指针。
在这里插入图片描述
B*树定义了非叶子节点关键字个数至少为(2 / 3) * M,即块的最低使用率为2/3(代替B+树的1/2)

B+树和B*树的分裂比较

  • B+树的分裂:当一个节点满时,分配一个新的节点,并将原节点中1/2的数据复制到新节点,最后在父节点中增加新节点的指针;B+树的分裂只影响原节点和父节点,而不会影响兄弟节点,所以它不需要指向兄弟的指针
  • B*树的分裂:当一个节点满时,如果它的下一个兄弟节点未满,那么将一部分数据移到兄弟节点中,再在原节点插入关键字,最后修改父节点中兄弟节点的关键字(因为兄弟节点的关键字范围变了);如果兄弟也满了,则在原节点与兄弟节点之间增加新节点,并各复制1/3的数据到新节点,最后在父节点增加新节点的指针

所以B*树分配新节点的概率比B+树要低,空间使用率更高,在B+树基础上,为非叶子节点也增加链表指针,将节点的最低利用率从1/2提高到2/3。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值