技.艺.道:B树

  • Post author:
  • Post category:其他


一、简介

名称:平衡多路查找树

出现的原因:为了解决 平衡二叉树在存储大量数据时的树过高的问题。

主要使用场景:数据库索引

二、定义与性质

基础1:B树节点的结构

1)叶子结点结构

叶子节点里面什么都没有,但它在逻辑上确实是一个结点。可以把它想象成一个空盒子。

2)非叶结点(即不是叶子结点的结点)结构


指针比


key


(关键字)多一个(多一个指针


0


),因为


key


是夹在指针之间的。


这里的“结点”指的是,它是构成


B


树的基本单元,在图中表示为这个淡黄色的圆角矩形。即


B


树是由多个该结构的结点构成的,这些结点的


n


可能等于任意正整数。它的形状就是下图这样。

基础2:B树的阶

B树中所有节点的孩子结点数(节点的指针数)的最大值称为B树的阶。下图为一棵3阶B树,因为该树的所有结点中,单个节点拥有的孩子结点数(指针数)最多为3

即key“78”和key“88”所在的节点,拥有三个子树(三个指针)。

基础3:终端结点

终端结点是叶子节点的父节点

性质1

在一棵

m


阶B树中,树中单个节点最多有


m


棵子树(即最多有


m-1





key




解析:这其实和“阶的定义”是对应的。换句话说就是:


m





B


树单个节点最多有


m


个指针。那么那个拥有


m


个指针的结点自然也就有


m-1





key







注意:这里的“最多”(至多),即:子树最多的那个节点,子树数目可以比


m


小。性质


1


限定了


B


树结点内部的最大规模。


性质


2


若根结点不是终端结点,则至少有两棵子树。


解析:该


B




若根结点是终端结点

若根结点不是终端结点

但是


性质


3


除根结点之外的所有非叶节点至少有


[m/2]


棵子树。


解析


:即图中绿色圆角矩形中的每个结点都至少要有


[m/2]





m


除以


2


,并向上取整)棵子树。


例如:这里是一棵


3阶B树,这里图中绿色圆角矩形中的每个结点都至少有([m/2]=[3/2]=[1.5]=1.5向上取整=2) 2棵子树。可以看到,这里是符合的。

性质3限定的是B树单个结点的最小规模。(性质1限定的是B树单个结点的最大规模)

性质4


非叶节点的结构


解析:节点上的指针指向的结点的


key


与当前结点的


key


,这些值从左到右是

以从小到大的顺序排列

的。


即:设


p


1v


表示指针


1


指向的结点的最大的


key





k1


表示


key1


的值,则有:


p


0v<k1<p1v<k2<p2v<…<kn<pnv


如该例子中的:


12<15<20<22<…<75<80


性质


5


所有的叶子节点都出现在同一层次上,并不带任何信息


解析:图中红色矩形框中的结点均为叶子节点,看得出它们都在最下层,并不带任何信息,因此用


null


表示。

三、常用操作

1.插入


B


树元素的插入


例如给定如下


key【


20,30,50,52,60,68,70





创建一个


3





B树。


(性质1要求子树数<=3,性质3要求子树数>=2)

插入20:


Ok


,满足


3





B树的性质,继续插入

插入30:


Ok


,满足


3





B


树的性质,继续插入

插入50:


NO





3





B


树最多只能有


3


个子树,这里有了


4


棵子树,违反了“性质


1


”;于是开始进行“结点的分裂”(提出中间位置(


[3/2]=2


)的


key 30


,将其作为独立节点。


Ok


,满足


3





B


树的性质,继续插入


插入52:


Ok


,满足


3





B


树的性质,继续插入

插入60:


No


,不满足


3





B


树的性质


1





这里有了


4


棵子树,违反了“性质


1


”;于是开始进行“结点的分裂”


Ok


,满足


3





B


树的性质,继续插入

插入68:


Ok


,满足


3





B


树的性质,继续插入

插入70:


No


,不满足


3





B


树的性质


1





这里有了


4


棵子树,违反了“性质


1


”;于是开始进行“结点的分裂”


No


,分裂之后仍然不满足


3





B


树的性质


1








里根节点有了


4


棵子树,违反了“性质


1


”;


于是继续进行


“结点的分裂”


Ok


,满足


3





B


树的性质,完成插入。

小结:插入操作主要涉及到两个操作,一是节点的分裂:

中间位置(


[3/2]=[1.5]=1.5向上取整=2


)key

的踢出,使其作为独立的结点。结点的合并:被踢出的中间key合并到其父节点,也可以看成是中间key先变成了独立结点,再与其父结点合并。

2.结点的删除

删除的关键:要使得删除后的结点中的key个数>=[m/2]-1,因此将涉及到结点的“合并”问题。可以分为关键字在终端结点上和不在终端结点上两种情况。

情况的划分:

1)关键字在终端结点上

1.1 结点内key数量>[m/2]-1,删除key不会破坏其作为B树的结构,可以直接删除。

1.2 结点内key数量=[m/2]-1,并且其左右兄弟结点中存在key数量>[m/2]-1的结点,则去兄弟结点中借key。


注释:从兄弟结点借


key





20”,将


它独立为一个节点,然后按照规则排列涉及到的节点。

1.3 结点内key数量=[m/2]-1,并且其左右兄弟结点中不存在key数量>[m/2]-1的结点,则需要进行结点合并。

2)关键字不在终端结点上

补充定义:

相邻关键字key:对于不在终端结点上的key,它的相邻key是其左子树中值最大的key和其右子树中值最小的key。注意是子树而不是子节点中。





20


”的相邻


key


:“


19


”和“


39







52


”的相邻


key


:“


50


”和“


60



需要先转换成在终端结点上,再按照在终端结点上的情况来分别考虑对应的方法。


删除“


52




第一


步:待删除


key


与位于终端结点的相邻


key


互换位置


第二步:删除换位之后的待删除


key



版权声明:本文为qq_32254003原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。