扁扁笨算法-B树的插入与删除

扁扁笨算法-B树的插入与删除

扁扁笨简述

扁扁笨算法是将不平衡子树打成一条中序遍历的直链(实质是一条升序链),然后按照寻找中点并提起中点构造二叉树的一种朴素做法。扁扁笨算法是一种确定平衡树调整结构之后填入数字的辅助手段,本身并没有什么出彩的地方。

理论简介

B树是一种强结构弱数据的数据结构。从B树的定义我们可以看到,B树的大部分要求都是在规范B树具有怎样的结构。从纯粹的数据排列上看,它只是一种扩展版的二叉排序树,但是B树之所以为B树就在于它的结构要求,其中比较重要的有,结点的元素个数、结点的指针个数。结点的元素个数描述了一个结点可以画几个格格,结点的指针个数描述了每个格格之间的边边指向下一层的结点。

之所以说,B树具备强结构弱数据的特点,是因为B树的操作和删除并不是很关系,数据的组织,因为排序树的特性,数据只需要按照简单的大小关系填入B树的框架里即可。或者说,给定一组数据序列,我们不能确定唯一的B树,而且异构的B树是复杂的。但一旦确定了B树的结构,我们就可以确定唯一的一棵B树,至于数据,依次填上去就好了。

所以,我们可以利用扁扁笨算法将结构与数据抽离开。将B树中某个数据元素的删除或者插入,转化为一种结构是如何演变为另一个结构的。在这种抽象的结构研究中,我们不关心结点的大小,但关心结点的个数和大小关系。

我们假设这是一棵5阶B树,那么首先我们应该写出它每个结点所容纳的结点范围:2~4,即一个非根结点最少不能少于2个结点,最多不能多于4个结点。

img

在开始删除操作之前,我们引入一些新的概念,我们将元素个数等于结点最少元素数的结点称为饥饿结点/贫瘠结点,元素个数等于结点最多元素的结点称为肿胀结点,除此之外我们称为温饱结点。在5阶B树的语境下,元素数为2的结点为饥饿结点,元素数为4的为肿胀结点,元素数为3的结点为温饱结点。如果整棵B树的结点均为贫瘠结点,那么我们称这棵树是贫瘠的

我们不妨进行一下讨论,当我们的删除发生在并不饥饿的结点(肿胀结点或者温饱结点)上时,整棵B树的结构不会发生改变。而当我们的删除发生在饥饿结点时,一定会引起结构的改变。

既然饥饿结点中元素的删除会引发结构改变,那我们的诉求就转变为了寻找这种结构改变。当删除贫瘠B树的贫瘠结点元素时,B树为了维持结构要求会通过“降层”的方式去填补下层缺失的结点。当删除非贫瘠B树的贫瘠结点时,贫瘠结点会被周围同层的温饱结点吸收。而吸收动作会引发下层结构缺位,这时降层得到的新的顶层就需要贡献一个结点给下层,用以维持结构。

插入操作有着类似的讨论,我们在下面进行展开。

当我们的插入发生在一个并不肿胀的结点(贫瘠结点或温饱结点)上时,,整棵B树的结构不会发生改变。而当我们的插入发生在肿胀结点时,一定会引起结构的改变。当元素插入到肿胀结点中时,就会引发结点爆炸,这个结点会分裂成为两个新的结点(这两个结点通常是温饱的)。但需要注意的是,为了维持该层多一个结点的结构,上层的指针也需要多一个,多一个指针需要下层结点为上层结点贡献一个元素。注意,在这种情况下,下层多一个结点导致上层也多一个结点,而上层多的这个结点也是有可能因为肿胀结点的插入而分裂,这种情况就会不断传递给上层,直到根结点。

插入举例

第一个例子

如图所示5阶B树,插入元素10

img

插入位置的结点已经肿胀,插入元素10发生结点爆炸。B树的结点发生改变,此时采用扁扁笨策略将改变结构的数据记录到一条升序链中。

img

在结构确定之后,将扁扁链的数据按顺序回填到B树,完成B树的调整。

img

第二个例子

如图所示5阶B树,插入元素20

img

插入位置的结点已经肿胀,插入元素20发生结点爆炸。B树的结点发生改变,此时采用扁扁笨策略将改变结构的数据记录到一条升序链中。本例与上例相同。在结构确定之后,将扁扁链的数据按顺序回填到B树,完成B树的调整。

img

第三个例子

如图所示5阶B树,插入元素15

img

插入位置的结点已经肿胀,插入元素15发生结点爆炸。B树的结点发生改变,此时采用扁扁笨策略将改变结构的数据记录到一条升序链中。

img

第一次结构调整后引发第二次结点爆炸(称为连环爆炸)。

img

在结构确定之后,将扁扁链的数据按顺序回填到B树,完成B树的调整。

img

删除举例

第一个例子

如图所示3阶B树,删除元素50

img

{53,90}这个结点丢失一个孩子,那么以这个结点为根的子树将进行结构调整。

同时采用扁扁笨策略将改变结构的数据记录到一条升序链中。

由于这棵树并不贫瘠,且存在温饱的孩子结点,那么由{61,70}结点分出一个元素位填补结构。

img

在结构确定之后,将扁扁链的数据按顺序回填到B树,完成B树的调整。

img

第二个例子

如图所示3阶B树,删除元素53

img

{61,90}这个结点丢失一个孩子,那么以这个结点为根的子树将进行结构调整。

同时采用扁扁笨策略将改变结构的数据记录到一条升序链中。

由于这棵树并不贫瘠,且孩子均是贫瘠结点,那么由{61,90}结点分出一个元素位填补结构。

img

在结构确定之后,将扁扁链的数据按顺序回填到B树,完成B树的调整。

img

第三个例子

删除43

img

第一种思路:找左孩子

左孩子并不贫瘠,则{35,41}结点贡献一个元素位。

img

在结构确定之后,将扁扁链的数据按顺序回填到B树,完成B树的调整。

img

第二种思路:找右孩子

由于右子树的根结点已经肿胀,不能与左子树合并,因此由右根贡献一个元素位充当新的根结点维持结构。

img

在结构确定之后,将扁扁链的数据按顺序回填到B树,完成B树的调整。

img

第四个例子

删除50

img

观察发现左右子树均为贫瘠树,所以拿走根结点维持结构。

img

调整结构

img

在结构确定之后,将扁扁链的数据按顺序回填到B树,完成B树的调整。

img

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值