数据结构:B树&B+树

在学习B树之前,建议先了解二叉查找树,平衡二叉树,红黑树。它们的查找算法的时间复杂度为O(log2n),为了避免二叉查找树退化为线性链表,引入了平衡二叉树红黑树的数据结构。

确实二叉查找树在内存中的查找效率非常高,但是在大型的数据库存储中,实现索引查找如果采用二叉查找树查找的话,由于查找树中每个节点的存储数据是有限的,且因为查找树的结构特征,很可能导致遍历树的深度过大从而造成磁盘的IO操作过于频繁,就会导致效率非常低下。

一般来说,索引是很大的,往往以文件的形式存储的磁盘上,索引查找时会产生磁盘I/O消耗,相比起内存存取,I/O存取的消耗要高几个数量级,所以一个索引数据结构的优劣最重要的指标就是查找过程中磁盘I/O操作次数的时间复杂度。树越深,I/O次数越多,那么为了提高索引查找的效率,我们可以就通过减少树的深度对其进行优化。

此时就引入了平衡多路查找树结构。

这里说句题外话,B-Tree就是B树,不是B减Tree。有些人会认为BTree是平衡二叉树,B-Tree才是平衡多路查找树,这里说法不一就去纠结其对错了,毕竟只是名字而已。

 

B-树的定义

B树中,所有节点的孩子数最大值为B树的阶层M,从查找效率考虑,一般要求M≥3,通常情况下,M是很大的。

如下图所示:所有节点中,孩子数最大值为3,这是个3阶B树。

一个M阶的B树具有如下特性:

①根节点至少有两个子树

②树中每个节点最多包含M个孩子

③中间节点至少有ceil(M/2)个孩子:如图中,3阶树的中间节点至少要有2个孩子节点,但不能超过3个

④所有的叶子节点都位于同一层:看了很多关于B树的博文,其中对叶子节点是否能存储数据的说法都不一致,对于这个问题就自行判断即可。

以上①~④的特征都是为了保证B树的每个索引块尽可能多地存储索引信息,以此限制树的深度,尽可能减少从磁盘中查找数据时,IO的次数。

⑤假设每个非终端节点包含n个关键字信息,其中,

a. 对于关键字Ki(i = 1~n),各不相等(注意是节点中互不相等)且按顺序升序排序,K(i-1) < Ki

b. 节点的关键字个数n比孩子节点数少1

c. 对于非叶子节点的指针P[1]~P[M],其中P[1]指向关键字小于K[1]的指针,P[M]指向关键字大于K[M-1]的子树,P[i]指向关键字属于(P[i-1]~P[i])

例如图中,P1指向的关键字都小于39,P2指向的关键字都大于39且小于87,P3指向的关键字都大于87

 

B树的查找流程

①从根节点开始,将目标关键字与节点中的多个关键字进行比较,找到其范围,然后去该范围中对应的子树进行寻找

②重复以上步骤,直到找到或到叶子节点还没找到为止。

还是拿上图举例吧,例如我们这时需要查找的关键字key = 66

1. 从根节点开始,与根节点的关键字比较大小后,确定范围在根节点P3所指向的节点。

2. 继续比较关键字,确定范围在39和87之间,也就是P2节点

3. 到达其叶子节点,查找到对应关键字。

注:这个情况是基于叶子节点是能够存储数据的,在有些文章中,叶子节点为NULL作用于查找失败的标志。

 

B树的插入流程

以如下3阶的B树为例:

①如果节点的关键字个数没有达到2,那么直接插入

②如果关键字超过2了,那么需要对节点进行分裂

分裂的规则是该结点分成两半,取中间的关键字进行提升,加入到父亲结点中,此时有可能存在父亲结点也满员的情况,则不得不向上进行回溯,甚至是要对根结点进行分裂,那么整棵树都加了一层。

插入26后,节点关键字个数超过2个需要分裂

于是取30到父节点,26作为中间子树,37作为右子树。经过调整后该树符合B树特征。

 

根节点回溯的情况就不分析了,图实在太难画了...反正只要记住关键字数超过以后分裂就可以了。

删除的逻辑其实也差不太多,我实在是太懒所以就过了,主要是不配图很难受,配的话又太麻烦(●'◡'●)

 

B树的大概就这些,下面说一下B+树。

 

B+树是B树的一种变形,它要比B树更适合操作系统的文件索引或数据库索引,在实际中也是大部分主流数据库的索引数据结构。

B+树的定义

下图是一个3阶B+树,可以看到同样是3阶,B+树比起B树就胖了很多呵

下面是B+树的特征:

①非叶子节点的子树指针与关键字个数相同:B树中关键字数要比子树指针数少1

②非叶子节点的子树指针P[i],指向关键字值[K[i],K[i+1])的子树:例如根节点的P1指针向的是关键字为[5,28)以内的子树

③非叶子节点仅用于索引,数据都保存在叶子节点中:B树中有的指向文件的关键字是在内部节点中

④所有叶子节点都有一个链指针指向下一个叶子节点:B树的叶子节点不存在该链指针

 

根据其特征,在文件系统或数据库中B+树相比起B树要更具优势,原因如下:

①磁盘读写代价更低:因为B+树的内部节点并不存在指向关键字具体信息的指针,只充当索引,这样一个节点就可以存储更多的索引关键字。相对来说,磁盘IO的次数比起B树就更小。

 

②查询效率更加稳定:由于内部节点只充当叶子节点中关键字的索引,所以任何关键字的查找路径都必须从根节点到叶子节点。也就是说,不论查询任何关键字,其效率都是一样的。

 

③更有利于对数据库的扫描:可以在图中看到,B+树相比起B树最大的不同就在于其所有叶子节点都有一个链指针指向下一个叶子节点,因此,B+树只需要遍历叶子节点的链表,就可以实现对全部关键字信息的扫描,所以对于数据库中频繁使用的范围查询,B+树相比起B树效率要高很多。


以上就是一些关于B树和B+树的知识点,不保证完全准确,因为很多概念都是从不同的博客中搜刮过来的(●'◡'●),最后希望今后我与本篇的读者们都能够做到心里有B树。

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值