【tree】B+树

本文目录

  • 一、B+树的定义
  • 二、B+树的查找
  • 三、B+树的插入
  • 四、B+树的删除

系列目录

本文转载自:一文彻底弄懂B树和B+树 (xianzilei.cn)


一、B+树的定义

B+树是B树的一种变形形式。网上各种资料上B+树的定义各有不同,一种定义方式是关键字个数和孩子节点个数相同。这里我们采取维基百科上所定义的方式,即关键字个数比孩子节点个数小1,这种方式是和B树基本等价的。除了B树的性质,B+树还包括以下要求:

  • 1)B+树包含2种类型的节点:内部节点(也称索引节点)叶子节点。根节点本身即可以是内部节点,也可以是叶子节点。根节点的关键字个数最少可以只有1个。
  • 2)B+树与B树最大的不同是内部节点不保存数据只用于索引,所有数据(或者说记录)都保存在叶子节点中
  • 3) m阶B+树表示了内部节点最多有m-1个关键字(或者说内部节点最多有m个子树),阶数m同时限制了叶子节点最多存储m-1个记录
  • 4)内部节点中的key都按照从小到大的顺序排列,对于内部节点中的一个key,左树中的所有key都小于它,右子树中的key都大于等于它。叶子节点中的记录也按照key的大小排列。
  • 5)每个叶子节点都存有相邻叶子节点的指针,叶子节点本身依关键字的大小自小而大顺序链接。

上图是一棵阶数为4的B+树


二、B+树的查找

操作流程同B树的搜索流程,只不过如果要找的关键字匹配上了索引节点的关键字,需要继续往下找,因为索引节点不存储数据,所有的数据都存储在叶子节点上。

B树的搜索流程见:【tree】B树_厚积薄发者,轻舟万重山-优快云博客


三、B+树的插入

3.1 基本步骤

  • 1)若为空树,创建一个叶子节点,然后将记录插入其中,此时这个叶子节点也是根节点,插入操作结束。
  • 2)针对叶子类型节点:根据key值找到叶子节点,向这个叶子节点插入记录。插入后,若当前节点key的个数小于等于m-1,则插入结束。否则将这个叶子节点分裂成左右两个叶子节点,左叶子节点包含前m/2个记录,右节点包含剩下的记录,将第m/2+1个记录的key进位到父节点中(父节点一定是索引类型节点),进位到父节点的key左孩子指针向左节点,右孩子指针向右节点。将当前节点的指针指向父节点,然后执行第3步。
  • 3)针对索引类型节点:若当前节点key的个数小于等于m-1,则插入结束。否则,将这个索引类型节点分裂成两个索引节点,左索引节点包含前(m-1)/2个key,右节点包含m-(m-1)/2个key,将第m/2个key进位到父节点中,进位到父节点的key左孩子指向左节点, 进位到父节点的key右孩子指向右节点。将当前节点的指针指向父节点,然后重复第3步。

3.2 图文说明

以5阶B+树为例(5阶B+树节点最多有4个关键字,最少有2个关键字,其中根节点最少可以只有一个关键字),从初始时刻依次插入数据。

  • 1)在空树插入5

  • 2)依次插入8,10,15

  • 3)插入16

    此时节点超过关键字的个数,所以需要进行分裂。由于该节点为叶子节点,所以可以分裂出来左节点2个记录,右边3个记录,中间key成为索引节点中的key(也可以左节点3个记录,右节点2个记录),分裂后当前节点指向了父节点(根节点)。结果如下图所示

    当前节点的关键字个数满足条件,插入结束

  • 4)插入17

  • 5)插入18

    当前节点超过关键字的个数,进行分裂。由于是叶子节点,分裂成两个节点,左节点2个记录,右节点3个记录,关键字16进位到父节点(索引类型)中,将当前节点的指针指向父节点,如下图所示

    当前节点的关键字个数满足条件,插入结束

  • 6)同理继续插入6,9,19,细节不再描述

  • 7)继续插入7

    当前节点超过关键字的个数,进行分裂。由于是叶子节点,分裂成两个节点,左节点2个记录,右节点3个记录,关键字7进位到父节点(索引类型)中,将当前节点的指针指向父节点,如下图所示

    当前节点超过关键字的个数,进行分裂。由于是索引节点,左节点2个关键字,右节点2个关键字,关键字16进入到父节点中,将当前节点指向父节点,如下图所示

    当前节点的关键字个数满足条件,插入结束


四、B+树的删除

4.1 基本步骤

如果叶子节点中没有相应的key,则删除失败。否则执行下面的步骤:

  • 1)删除叶子节点中对应的key。删除后若节点的key的个数大于等于Math.ceil(m-1)/2 – 1,删除操作结束,否则执行第2步。
  • 2)若兄弟节点key有富余(大于Math.ceil(m-1)/2 – 1),向兄弟节点借一个记录,同时用借到的key替换父结(指当前节点和兄弟节点共同的父节点)点中的key,删除结束。否则执行第3步。
  • 3)若兄弟节点中没有富余的key,则当前节点和兄弟节点合并成一个新的叶子节点,并删除父节点中的key(父节点中的这个key两边的孩子指针就变成了一个指针,正好指向这个新的叶子节点),将当前节点指向父节点(必为索引节点),执行第4步(第4步以后的操作和B树就完全一样了,主要是为了更新索引节点)。
  • 4)若索引节点的key的个数大于等于Math.ceil(m-1)/2 – 1,则删除操作结束。否则执行第5步
  • 5)若兄弟节点有富余,父节点key下移,兄弟节点key上移,删除结束。否则执行第6步
  • 6)当前节点和兄弟节点及父节点下移key合并成一个新的节点。将当前节点指向父节点,重复第4步。

注意,通过B+树的删除操作后,索引节点中存在的key,不一定在叶子节点中存在对应的记录。

4.2 图文说明

以5阶B树为例(5阶B树节点最多有4个关键字,最少有2个关键字,其中根节点最少可以只有一个关键字)。初始时刻以上述插入操作的最终状态为例。

  • 1)初始状态

  • 2)删除22

    删除后叶子节点中key的个数大于等于2,删除结束

  • 3)删除15

    当前节点只有一个key,不满足条件,而兄弟节点有三个key,可以从兄弟节点借一个关键字为9的记录,同时更新将父节点中的关键字由10也变为9,删除结束。

  • 4)删除7

    当前节点关键字个数小于2,(左)兄弟节点中的也没有富余的关键字(当前节点还有个右兄弟,不过选择任意一个进行分析就可以了,这里我们选择了左边的),所以当前节点和兄弟节点合并,并删除父节点中的key,当前节点指向父节点。

    此时当前节点的关键字个数小于2,兄弟节点的关键字也没有富余,所以父节点中的关键字下移,和两个孩子节点合并,结果如下图所示。

    删除结束。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值