B树是什么?有什么作用?B树的插入和删除具体细节是什么?除了B树还有一个是B+树、还是B-树,他们有什么区别,又有什么相同点?
b树在王道考研查找这一章,所以他的主要作用就是查找。
在学习b树之前,先要回顾一下二叉查找树。他的结构体是:
typedef struct BSTNode{
int key;
struct BSTNode *lchild,*rchild;
}BSTNode,*BSTree;
不难看出它的结构,下面给个图示,就更加简洁明了了。
我们有个想法,能不能增加更多的分类?就是说从二叉查找树变成m叉查找树。于是b树就产生了。
结构体如下:
struct Node{
ElemType keys[4];
struct Node *chile[5];
int num; //结点中有几个关键字
};
从上面我们可以知道,假如一个结点有四个关键字,那么有五个分叉。
即如图所示:
有了这张图片就清晰很多了,同时也指出了几个特点:节点内关键字有序(方便查找,从结构体内我们知道,结点里是数组),根结点最少有一个关键字(很好理解,根结点假如没有关键字,那他不能向下分叉)。
这里还有一个规定,除根结点外(老大特殊),每个接点都有最少得关键字限制(为了提高查找效率,如果都是一个关键字,那和二叉查找树有什么区别?)
先说分叉,至少有一半以上的分叉,假如child[4],->至少两个分叉、child[5]->至少是有3个分叉。即偶数/2,奇数/2再四舍五入。
还有一个策略是忽略的,就是在m叉查找树中,任何一个节点,其所有子树的高度都要相同。也就是说所有叶结点都在同一层。b树的叶子结点是查找失败的结点。
b树的插入:
一个一个插入:溢出之后把他们从中间劈开、分给左右孩子。注意:新节点一定是插在终端节点那一层!(未溢出时)
此时中间劈开原结点分给父节点(这里体会到了结点内关键字有序的好处)这里还是把80移到父节点。规律总结:在插入key后,若导致原结点的关键字数超过上限,则从中间位置将其分成两部分,左部分放在原结点,右部分包含的关键字放到新节点,中间位置插入原结点的父节点。
若根结点满了!继续分裂:
b树的删除:
分多种情况:
终端节点:直接删除!(但是要注意删除完成之后,该结点的关键字个数是否小于一半)
非终端结点:用直接前驱替代:
用直接后继替代:
兄弟够借(找父母要,然后兄弟补给父母):右兄弟富裕
:删除38
左兄弟富裕:删除92
兄弟不够借:
b+树:
图中是四阶b+树,下面说一下特点:分叉情况和b树一样。
结点的子树与关键字数相等。
所有叶结点包含全部的关键字,大小顺序排列,且相邻叶结点按大小顺序相互链接起来。
所有分支结点中仅包含它的各个子节点中关键字的最大值及指向其子节点的指针。
对比:b树的关键字每一层都有,而b+树的关键字只可能是在叶子结点。
真题训练:
注意:b-树也叫作b树。