B树详解 数据与结构

B-树:

       
首先我们需要明确一点:1970年,R.Bayer和E.mccreight提出了一种适用于外查找的树
,它是一种平衡的多叉树,称为B树(或B-树、B_树)。所以我们现在所说的B树和B-树其实指的是同一个东西。在这里我们就称它为B树吧。

B树的定义、基本概念:

       首先我们定义B树的阶:B树中所有节点中孩子节点个数的最大值,通常我们用m表示(m >= 3),成为m阶B树。
那么我们就不得不提一下2-3树是什么东西了,2-3树其实就是最简单的B树,每个非叶子节点都有2-3个孩子节点,所以2-3和3阶B树是同一个东西。m阶B树所满足一下的性质。


1)每个节点最多有m个分支(子树),除根节点和叶子节点之外的节点最少都应该含有ceil(m/2) 个分支(ceil表示向上取整),所以非根非叶子的分支的数量范围为 [ ceil(m/2),m]。根节点最少可以有两个分支


2)某个节点中含有m个分支,那么它所包含的关键词就是(m-1)个,所以在m阶B树中,他的关键词的数量范围就是[ceil(m/2)-1,m-1] ,并且在节点中关键词的都是按照递增顺序排列的。


3)出叶子节点外所有的节点中的关键词都是互不相等的。


如果说有一个这样的说法:B-树中一个关键字只能在树中某一个节点上出现,且节点内部关键字是有序排列的。这个说法是正确的。
4)B树中的叶子节点都是处在同一层中,一般都是用空指针表示,表示查找失败。


5)B树中某个节点中左子树所有的关键词都是小于这个节点的,右子树中所有的关键词都是大于这个节点的。这里就是和二叉排序树是相同的
《B树详解 数据与结构》

        
说明:此图中的叶子节点在最后连线的下方,第三层不是叶子节点


我们结合上面的这个图片来详细的说明一下B树的基本概念。首先我们可以看到这课B树的阶数是3,称为3阶B树,那么它除了根节点个叶子节点分支的数量范围就是[2,3]([ceil(m/2),m]),对应节点的关键词的数量范围是[1,2]([ceil[m/2]-1,m-1])
我们可以看到除叶子节点之外所有节点中的关键词都是不相同的,并且在每个节点内部,关键词的排序都是按照递增的顺序排列的。并且在同一层中,左边节点中所有的关键词均小于右边节点中的关键词。
叶子节点都是在第四层,表示不成功的查找。

B树的查找:

        
B树的查找查找成功就是在除叶子节点之外的点中找到了值相等的关键词,失败就是指一直到叶子节点都没有找到相等的关键词。
      我们假设需要查找的关键词是key,查找的过程 如下:
1)key先和根节点中的关键词比较,如果在在节点中找到key == k[i](表示节点中第i个关键词),那么就表示查找成功。
2)如果上面的节点没有找到匹配的值,我们就需要在再节点的关键词中寻找 k[i] < key  <k[i+1] ,或者 key < k[0],或者 key > k[n],然后根据指针所指示的子树继续查找。
3)如果最后遇到空指针,则证明查找不成功。


        我们拿上面的二叉树进行一下演示,假设我们要查找  元素P  和  元素Z  :
《B树详解 数据与结构》

        上图表示的是查找元素P的过程,最后查找到了结果。
《B树详解 数据与结构》

        我们查找元素Z,每次都找到元素所存在的位置,然后一路往西,最后到了叶子节点,成空了,表示查找失败,这个B树中没有这个元素。

B树的插入:

        在B树插入的过程中我们主要需要注意的就是各个节点中关键词的个数,我们上面说过关键词的个数范围应该在 ([ceil[m/2]-1,m-1])之间。在插入过程中首先应该在B树中找到我们需要插入的位置,如果这个待插入的元素以前是不存在于B树中的,我们就一直会找到叶子节点上,那么我们需要的位置就是这个叶子节点之上的子节点中相应位置。我们这里称底层非叶子节点为底层节点,所以我们一般找到的位置都是在底层节点上,我们先将待插入的节点插入到这个底层节点中,然后我们需要考虑关键词超限的情况。也就是说如果你太富裕了,需要和那些比较穷的节点中和一下,保持一个平衡的状态。
        我们就新建一棵B树,以关键序列{3,7,2,5,4,11,10,9,13,8,1,12,6,15}建立一棵5阶B树。
        可以得到除根节点和叶子节点之外,每个节点的关键词数目范围为  [2,4]


1)首先插入{3,7,2,5,4},在插入{3,7,2,5}过程中都没有违背5阶B树的性质,在插入{4}之后节点中就有5个关键词了,那么我们就需要选取中间节点作为根节点,剩下的作为左子树和右子树的节点。
《B树详解 数据与结构》

                  《B树详解 数据与结构》



2)然后我们再插入元素{11,10,9},在插入{11,10}之后我们的右子树已经到达关键词的上限,往后再次插入元素{9},我们的右子树就不满足5阶B树的性质了,我们就需要将过度富裕的右子树中,拿出中间的一个关键词给它的父亲节点。
《B树详解 数据与结构》

《B树详解 数据与结构》
3)然后我们继续进行插入,{13,8,1,12,6,15},直到插入元素{15}的时候我们又会发现过度富裕的节点,然后同样需要我们将中间节点给它的父亲。
《B树详解 数据与结构》

《B树详解 数据与结构》



4)最后我们得到了我们的5阶B树。
        在插入时,我们还有时会遇到另外一种情况:父亲节点已经到达上限,但是它的子节点中又含有一个过度富裕的,那么我们应该怎么办…….
        这是将我们的过度富裕的节点中的中间关键词拿到父亲节点,这是我们的根节点就是过度富裕的了,这时根节点就没有父亲节点了,那么我们只好通过增加树的高度来完成了。
例:
《B树详解 数据与结构》
我们在这里面插入元素{17}


《B树详解 数据与结构》

这样我们的B树插入的操作经说的差不多了。
注:我们这里的B树都没有画失配的叶子节点。

B树的删除:

删除中我们首先需要找到待删除的关键词,当然在删除过程中我们有事也会破坏B树的特性,这时我们就需要进行一定的操作

来使这棵树重新成为B树。
详细操作:
首先我们需要知道元素的相近元素:如果某一个元素存在左右孩子节点的话,那么他的左孩子中的最大值和右孩子的最小值就是这个
元素的相近节点。

1)第一,我们要在B-树找到需要删除的元素的位置,将该节点进行删除,如果该元素存在相近元素,我们就把相近元素上移到父节
点中,然后进行后面的移动,如果没有相近节点,那么我们就直接进行后面的移动。
2)如果某节点中元素个数小于最小的元素数目,首先我们先看看相邻的兄弟节点是否过得还富裕,如果过的还富裕的话,那么直接
平均一下节点的关键词数目就好。
3)如果相邻的兄弟节点都是过的十分紧迫,那么我们就和邻近的兄弟节点以及一个父亲节点进行合并操作,然后再进行后面的移
动。

我们假设开始的B树是这样的:
《B树详解 数据与结构》

1)首先我们先删除关键词{12}
因为元素{12}所在的节点包含三个节点,所以直接删除不会影响我们5阶B树的性质,所以直接删除就好。
《B树详解 数据与结构》



2)我们删除节点19,我们发现元素节点{19}之后,节点就不满足5阶B树的性质了,这时候我们就要看看兄弟节点时候富裕,我们
发现右边的兄弟过的还好,我们就从他那里拿最左边关键词吧……
拿关键词就是先
把这个关键词先拿到根节点,再把根节点上的相应节点拿下来放到以前{19}的位置。
《B树详解 数据与结构》


3)如果我们想要删除元素{3}应该怎么办呢?我们首先将相近元素放到这个元素3所在的位置,于是我们就选取4吧
于是我们首先
得到了这样的B树:
《B树详解 数据与结构》






然后我们发现有一个节点只是包含一个元素,不符合5阶B树的性质,又因为{6}的左右兄弟节点都是刚刚脱贫,又不能向父亲节 点借,那么怎么办嘞…..只好进行合并操作了,那么我们就将含有{1,2}元素的节点和含有{6}的节点合并成一个节点,那么我们就 会得到这样的B树:

《B树详解 数据与结构》

这样又出现了一个节点7,他的相邻节点也不是十分富裕,我们只好再次向上合并,得到我们最后的5阶B树:
《B树详解 数据与结构》

这样我们的B树的所有操作就基本完成了。
这几天刚刚考完数据与结构,感觉自己在B树这里还不是很清楚,所以写了这个博客,如果有错误的话,大家可以在评论区留言,谢谢。



    原文作者:B树
    原文地址: https://blog.csdn.net/li1615882553/article/details/78915461
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞