B树和B+树

1.B树

1.1 B树的定义

  • 每个节点最多有m-1个关键字(可以存有的键值对)
  • 根节点最少可以只有1个关键字
  • 非跟节点至少有m/2个关键字
  • 每个节点的关键字都按照从小到大的顺序排列,每个关键字的左子树中的所有关键字都小于它,而右子树中的所有关键字都大于它
  • 所有叶子节点都位于同一层,或者说根节点到每个叶子节点的长度都相同
  • 每个节点都存有索引的数据,就是对应的key和value

     所以,跟节点的关键字数量范围:1<= k <= m-1,非根节点的关键字数量范围:m/2 <= k <= m-1。另外,描述一个B树时需要指定它的阶数,一般用m表示。

    举个路子,一颗5阶的B树,根节点数量范围:1<= k <= 4,非根节点数量范围:2<= k <= 4。

1.2 B树插入

插入的时候,我们需要记住一个规则:判断当前结点key的个数是否小于等于m-1,如果满足,直接插入即可,如果不满足,将节点的中间的key将这个节点分为左右两部分,中间的节点放到父节点中即可。

例子:在5阶B树中,结点最多有4个key,最少有两个key

-  插入18,70,50,40

- 插入22

插入22时,发现这个节点的关键字已经大于4了,所以需要分裂,分裂之后,如下:

- 接着插入23、25、39

分裂之后,得到下面

1.3 B树的删除操作

原则:

  • 如果当前需要删除的key位于非叶子结点上,则用后继key(均指后继记录)覆盖要删除的key,然后在后继key所在的子支中删除该后继key。此时后继key一定位于叶子结点上,这个过程和二叉搜索树删除结点的方式类似。删除这个记录后执行第2步
  • 该结点key个数大于等于Math.ceil(m/2)-1,结束删除操作,否则执行第3步
  • 如果兄弟结点key个数大于Math.ceil(m/2)-1,则父结点中的key下移到该结点,兄弟结点中的一个key上移,删除操作结束
  • 否则,将父结点中的key下移与当前结点及它的兄弟结点中的key合并,形成一个新的结点。原父结点中的key的两个孩子指针就变成了一个孩子指针,指向这个新结点。然后当前结点的指针指向父结点,重复上第2步。

例子:原始状态

clip_image021

- 删除21,删除后结点中的关键字个数仍然大于等于2,所以删除结束。

clip_image023

- 删除27。27位于非叶子结点中,所以用27的后继结点替换它。可以看出27的后继为28,用28替换27,然后在该结点中删除28,如下图所示。

clip_image025

删除后发现,当前叶子结点的记录个数小于2,它的兄弟结点中有3个记录(还有一个右兄弟,选择右兄弟就会出现合并结点的情况),从左兄弟借一个key。然后父节点中28下移,兄弟结点中26上移,删除结束。

clip_image027

- 删除32

clip_image029

当删除后,当前结点中只有一个key,而兄弟结点中也仅有2个key。所以只能让父节点的30下移和这两个孩子结点中的key合并,成为一个新的结点,当前结点的指针指向父结点。

clip_image031

当前结点key的个数满足条件,故删除结束。

- 删除40,删除后结果如下:

clip_image033

同理,当前结点的记录数小于2,兄弟结点中没有多余key,所以父结点中的key下移,和兄弟(这里我们选择左兄弟,选择右兄弟也可以)结点合并,合并后的指向当前结点的指针就指向了父结点。

clip_image035

同理,对于当前结点而言只能继续合并了,最后结果如下所示。

clip_image037

合并后结点当前结点满足条件,删除结束。

2 B+树

2.1 B+树的描述

B+树和B树非常相似,首先看相同点

  • 根节点至少一个元素
  • 非根结点元素范围:m/2 <=k <= m-1

不同点

  • B+树中有两种类型的节点:内部节点(索引节点)和叶子节点。内部节点就是非叶子节点,内部节点不存数据,只存索引,数据都存储在叶子节点。
  • 内部节点中的key都按照从小到大的顺序排列,对于内部结点中的一个key,左树中的所有key都小于它,右子树中的key都大于等于它。叶子结点中的记录也按照key的大小排列。
  • 每个叶子结点都存有相邻叶子结点的指针,叶子结点本身依关键字的大小自小而大顺序链接
  • 父节点存有右孩子的第一个元素的索引。

一个B+树的例子

2.2 插入操作

技巧:当节点元素数量大于m-1的时候,按中间元素分裂成左右两部分,中间元素分裂到父节点当做索引存储,但是,本身中间元素还是分裂右边这一部分的

以一颗5阶B+树的插入过程为例,节点最少2个元素,最多4个元素。

- 插入5、10、15、20

- 插入25,此时元素数量大于4个,分裂

- 接着插入26,30,继续分裂

2.3 删除操作

对于删除操作是比B树简单一些的,因为叶子节点有指针的存在,向兄弟节点借元素时,不需要通过父节点了,而是可以直接通过兄弟节移动即可(前提是兄弟节点的元素大于m/2),然后更新父节点的索引;如果兄弟节点的元素不大于m/2(兄弟节点也没有多余的元素),则将当前节点和兄弟节点合并,并且删除父节点中的key

- 初始状态

- 删除10,删除后不满足要求,发现左边兄弟节点有多余的元素,所以去借元素,最后,修改父节点索引

- 删除元素5,发现不满足要求,并且发现左右兄弟节点都没有多余的元素,所以,可以选择和兄弟节点合并,最后修改父节点索引

- 发现父节点索引也不满足条件,所以,需要做跟上面一步一样的操作

3 应用

3.1 B树

B树大量应用在数据库和文件系统当中。设计思想是将相关数据尽量集中在一起,以便一次读取多个数据,减少硬盘操作次数。B树算法减少定位记录时所经历的中间过程,从而加快存取速度。

假定一个节点可以容纳100个值,那么3层的B树可以容纳100万个数据,如果换成二叉查找树,则需要20层!假定操作系统一次读取一个节点,并且根节点保留在内存中,那么B树在100万个数据中查找目标值,只需要读取两次硬盘。

如mongoDB数据库使用,单次查询平均快于Mysql(但侧面来看Mysql至少平均查询耗时差不多)
 

3.2 B+树

mysql使用B+树作为索引:

B+树相对B树的优点:

  1. B+树的所有Data域在叶子节点,一般都会进行一个优化,就是将所有的叶子节点用指针串联起来,遍历叶子节点就能获取全部数据,这样就能进行区间访问了。
  2. IO一次读数据是从磁盘上读的,磁盘容量是固定的,取数据量大小是固定的,非叶子节点不存储数据,节点小,磁盘IO次数就少

1、MyISAM

这里写图片描述

MyISAM中有两种索引,分别是主索引和辅助索引,在这里面的主索引使用具有唯一性的键值进行创建,而辅助索引中键值可以是相同的。MyISAM分别会存一个索引文件和数据文件。它的主索引是非聚集索引。当我们查询的时候我们找到叶子节点中保存的地址,然后通过地址我们找到所对应的信息

2、InnoDB

这里写图片描述

InnoDB索引和MyISAM最大的区别是它只有一个数据文件,在InnoDB中,表数据文件本身就是按B+Tree组织的一个索引结构,这棵树的叶节点数据域保存了完整的数据记录。所以我们又把它的主索引叫做聚集索引。而它的辅助索引和MyISAM也会有所不同,它的辅助索引都是将主键作为数据域。所以,这样当我们查找的时候通过辅助索引要先找到主键,然后通过主索引再找到对于的主键,得到信息。

MyISAM表索引在处理文本索引时更具优势,而INNODB表索引在其它类型上更具效率优势,同时MySQL高并发需要事务场景时,只能使用INNODB表。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值