B-树,B+树

B树的孩子有左父亲和右父亲,父亲又有左孩子和右孩子。且一个节点既能做左孩子也能做右孩子,很奇妙的树!

B树规则定义

一棵M阶(M>2)的B树,是一棵平衡的M路平衡搜索树,可以是空树或
者满足一下性质:
1. 根节点关键字的数量是[1,M-1]
2. 根节点孩子的数量树[2,M]
3. 每个非根节点至少有M/2(上取整)个孩子,至多有M个孩子
4. 每个非根节点至少有M/2-1(上取整)个关键字,至多有M-1个关键字

5. 所有的叶子节点都在同一层
6. 节点中关键字按升序排列,孩子永远比数据多一个
7. 孩子节点比左父亲大,比右父亲小
8. key值不会重复,原因和分裂过程有关

B树的节点由两个数组组成,上面的数组放data,下面的数组放孩子节点。

这是当M等于3的情况下B树的节点的样子,但是实际写代码的时候每个数组会多开一个空位
在这里插入图片描述

以上是定义,看完插入过程就全部理解了。

B树的插入过程

模拟一下B树的插入过程
用序列{53, 139, 75, 49, 145, 36, 101}构建B树的过程如下:

以M = 3为例子说明,下面每一个数组都多开了一个格子,方便讲述和实现,实际中也会多开一个格子

注意:插入一定是在叶子节点插入的

第一步:先插入53,毫无疑问是插在第一个格子的

在这里插入图片描述

第二步:插入139,也是直接插入

在这里插入图片描述

第三步:插入75,必须按照升序插入。

在这里插入图片描述

第四步:由于这个节点已经放满了,因此不能再放在这个节点了。当节点放满的时候,B树有一个过程叫做分裂,分裂过程如下:

  1. 创建一个兄弟节点,然后把右半部分M / 2个数据拷贝到兄弟节点
    在这里插入图片描述
  2. 再把第M / 2 - 1个节点拿走,放到根节点。理由也很简单,由于要保证孩子节点永远比数据多一,此时多了一个兄弟节点(根节点就多了一个孩子节点),因此根节点的数据也要多1.
    在这里插入图片描述
    以上就是分裂过程。

第五步:继续插入49,由于49比75小,在左边插入。由于要保持升序,如图:

在这里插入图片描述

第六步:继续插入145,由于145比75大,在右边插入

在这里插入图片描述

第七步:插入36,由于36比75小,因此在左边插入,又要保持升序,因此要挪动数据

在这里插入图片描述

很明显又要分裂了,按照上面说的,分裂

在这里插入图片描述
但是这并不符合搜索树的性质,因为53比75小,应该在75的左边,因此要调整顺序。调整完顺序如下:
在这里插入图片描述
下面是最重要的第8步,B树插入的最重要部分!!!

第八步:继续插入101,由于101大于75,应该插入到75的右边。

在这里插入图片描述
发现又又又要分裂了。分裂完一次之后发现根节点还要继续分裂。
在这里插入图片描述
注:**插入数据的时候还要更新自己孩子节点的父亲。**插入完139之后,

最终结果是这样的:
在这里插入图片描述

去可视化网站验证一下:确实是这样的
在这里插入图片描述

最后总结一下分裂过程:

  1. 当data个数等于M 的时候要分裂
  2. 分裂的时候M / 2(下取整)个的右半部分要给兄弟节点,第M / 2 个数据要给根节点。给的时候按照插入排序的思想给。
  3. 分裂完之后要重新把父子关系连好
  4. 分裂完之后还是要符合搜索二叉的性质

根据分裂过程记忆性质(重要)

  1. 非根节点至少有M/2-1个数据.

在偶数情况下:假设M = 10,分裂时就会被分成4 1 5,因此非根节点有M / 2 - 1。
在奇数情况下:假设M = 9,分裂时就会被分成4 1 4,因此非根节点有M/2个。

  1. 非根节点最多有M-1个数据是B树的定义。
  2. 非根节点至少有M/2个孩子,因为孩子比数据多1
  3. 非根节点最多有M个数据,这是B树的定义

B树平衡过程:只有在满了的时候才会分裂出新节点,且新节点和原节点在同一层。也就是说:新节点都是在同一层横向产生的。
根节点分裂,才会增加高度,新增一层。
总结:B树是横向和向上生长,天然就平衡的,不需要旋转

实际中,像文件系统或者数据库中用B树及其变形,索引数据。一般M都会很大,一般都会设置成1024

在这里插入图片描述
假设一个小块存一个字节,1w亿就是1TB了,我的手提电脑才512个G。
所以用B树的话基本上4次io就可以找到你想要的数据了。

B树增删查改的时间复杂度: log ⁡ M N \log_M{N} logMN因为它是二分之M分的

B+树

B+树和B树规则差不多,主要差别在于

  1. 分裂过程稍有不同
  2. key值允许重复
  3. 叶子节点才存keyvalue结构,其余节点只存key
  4. 叶子节点用指针连接起来,可以看成一个链表

强调一个点:B+树和B树的M定义都是一样的,没有任何不同,都是M路平衡多叉树,也就是孩子节点最多为M,关键字最多为M-1个。

B+的插入过程

  1. B+树插入都是在叶子结点进行的,就是插入前,需要先找到要插入的叶子结点。
  2. 如果被插入关键字的叶子节点,当前含有的关键字数量是小于阶数m,则直接插入。
  3. 如果插入关键字后,叶子节点当前含有的关键字数目等于阶数m,则插,该节点开始「分裂」为两个新的节点,左边一个节点包含⌊m/2⌋ 个关键字,右边另外一个关键字包含⌈m/2⌉个关键值。(⌊m/2⌋表示向下取整,⌈m/2⌉表示向上取整,如⌈3/2⌉=2)。
  4. 分裂后,需要将第⌈m/2⌉的关键字上移到父结点。如果这时候父结点中包含的关键字个数小于m,则插入操作完成。
  5. 分裂后,需要将⌈m/2⌉的关键字上移到父结点。如果父结点中包含的关键字个数等于m,则继续分裂父结点。

总结一下就是:和B树一样,唯一区别在于如何对待第M / 2个元素,B树是直接剪切到父亲节点上,B+树是复制到父亲节点上,这也是为什么B+树key值会有重复的,因为有复制操作。

ps:个人认为不需要记插入过程,只要你知道是拿一半给兄弟,给一个给父亲。其他的你只要保证搜索树的性质没有被破坏你插入的就是对的。

举个例子:
43,48,36,32,M = 3

插入43,48,36后
在这里插入图片描述

由于大于两个关键字了,开始分裂。
记住左边下取整,右边上取整,然后把第M/2(上取整)个key复制给父节点
在这里插入图片描述

插入32
在这里插入图片描述
验证一下结果:
在这里插入图片描述

再举个例子
插入15,18,20,30,49,50,M = 4

注意是20和49拿给父亲,而不是18和30.因为18和30不符合性质了。

最后结果:
在这里插入图片描述

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值