1、
》》 B 树,又称为“ 多路平衡查找树 ” , B 树中所有结点的孩子结点数的最大值称为 B 树的阶,
通常用 m 表示。
》》 一棵 m 阶B 树或为空树,或为满足如下特性的 m 叉树:
1)、树中每个结点至多有 m 棵子树(即至多含有 m-1 个关键字)
2)、若根结点不是终端结点,则至少有两棵子树
3)、除了根结点外的所有非叶子结点至少有 棵子树(即至少含有
个关键字)
4)、所有的非叶子结点的结构如下:
解释: Ki (i=1,2,3,...,n)为结点的关键字,且满足 K1<K2<K3<...<Kn
Pi (i=0,1,2,3,...,n)为指向子树根结点的指针,且 Pi-1 所指子树中所有结点
的关键字均小于 Ki , Pi 所指子树中所有结点的关键字均大于 Ki
n () 为结点中关键字的个数
5)、所有的叶子结点都出现在同一层次上,并且不带信息。
》》 B 树是所有结点的平衡因子均等于 0 的多路查找树。
》》 如下图为一棵 3 阶B 树,其中底层的方形结点表示“ 叶子结点 ” ,在这些结点中没有存储任何信息。
2、B 树的查找
》》 在 B 树上进行查找与二叉查找树很相似,只是每个结点都是多个关键字的有序表,在每个结点上
所做的不是两路分支决定,而是根据该结点的子树所做的多路分支决定。
》》 B 树的查找包含两个基本操作:
第一:在 B 树中找结点【由于 B 树常存储在磁盘上,则本次操作是在磁盘上进行的】
第二:在结点内找关键字【本次操作是在内存中进行的,即在找到目标结点后,先将结点中的信息
读入内存,然后再采用“ 顺序查找 ”或者 “ 折半查找 ” 查找等于 K 的关键字】
》》 查找的思路
在 B 树上查找到某个结点后,先在有序表中进行查找,若找到则查找成功,否则按照
对应的指针信息到所指的子树中查找。当查找到叶子结点时,则说明树中没有对应的关键字,
查找失败。
3、B 树的插入
》》 在 B 树中找到插入的位置后,并不能简单地将其添加到终端结点中去,因为此时可能会导致
整棵树不再满足 B 树中定义中的要求。
》》 将关键字 key 插入到 B 树的过程如下:
步骤一:定位
利用 B 树的查找算法,找出插入该关键字的最底层中某个非叶结点(注意:B 树中
中的插入关键字一定是插入在最底层中的某个非叶结点内)。
步骤二:插入
在B 树中,每个非失败结点的关键字个数都在 之间。当插入后的
结点关键字的个数小于 m ,则可以直接插入;插入后检查被插入结点内关键字的个数,
当插入后的结点关键字个数大于 m-1 的时候,则必须对结点进行分裂。
【重点】分裂的方法
取一个新的结点,将插入 key 后的原结点从中间位置将其中的关键字分为两部分,
左部分包含的关键字放在原结点中,右部分包含的关键字放到新的结点中,中间位置
()的结点插入到原结点的父结点中。若此时导致其父结点的关键字个数也
超过了上限,则继续进行这种分裂操作,直至这个过程传到根结点为止,这样导致 B 树
的高度加 1 。
》》 结点“ 分裂 ”示意图
4. B 树的删除
》》 B 树中的删除操作:要使得删除后的结点中的关键字个数 ,因此涉及“结点的合并”问题。
》》 情况一:当所删除的关键字 k 不在终端结点(最底层非叶结点)中时【分以下几种情况】
1)、如果小于 k 的子树中关键字个数 ,则找到 k 的前驱值 kq ,并且用 kq 来
取代 k ,再递归地删除 kq 即可。
2)、如果大于 k 的子树中关键字个数 ,则找到 k 的后继值 kq ,并且用 kq 来取代
k ,再递归地删除 kq 即可。
3)、如果 k 的前后两个子树中关键字个数均为 ,则直接将这两个子结点合并,
直接删除 k 即可。
###案例:
》》 情况二:当被删除的关键字在终端结点(最底层非叶结点)中时【分以下几种情况】
1)、直接删除关键字
若被删除的关键字所在结点的关键字个数为 ,表明删除该关键字后仍然满足
B 树的定义,则直接删去该关键字。
2)、兄弟够借
若被删除关键字所在结点删除前的关键字个数为 ,且此相邻结点的右(左)
兄弟结点的关键字个数 ,需要调整该结点、右(左)兄弟结点以及其双亲结点
(父子结点换位法),以达到新的平衡。
## 案例:
3)、兄弟不够借
若被删除关键字所在结点删除前的关键字个数为 ,且此时与给结点相邻的
右(左)兄弟结点的关键字个数 ,则将关键字删除后与右(左)兄弟结点及
双亲结点中的关键字进行合并。
《
*** 在合并的过程中,双亲结点中的关键字个数会减少。
*** 若其双亲结点是根结点并且关键字个数减少至0 ,则直接将根结点删除,合并后
的新结点成为根
*** 若双亲结点不是根结点,且关键字个数减少到 ,又要与它自己的兄弟
结点进行调整或者合并操作,重复上面的步骤,直至符合 B 树的要求为止
》
### 案例: