cmu15445 22fall p2 b plus tree checkpoint1

bplustree

在这里插入图片描述
这篇文章主要讲讲task2,插入和删除操作时代码实现上的一些逻辑细节,伪代码可以看数据库帆船书第7版英文的(第6版中文版插入操作伪代码有错误)。

b+树发生分裂的条件是叶子节点中元素已满。时机可以选择插入后判断节点已满再分裂,也可以选择节点已满时插入失败再发生分裂。(我选择的为后者)

发生合并或借的条件是当前节点元素小于minsize,是借还是合并主要看兄弟节点元素是大于minsize还是小于等于minsize。

minsize = 向上去整maxsize/2

1.节点插入时,若元素数量>=maxsize时插入失败,进行分裂
2.节点删除时,若元素数量<minsize时,兄弟节点n’若元素数量大于minsize进行借操作,元素数量<=minsize则进行合并操作
3.在内部节点进行合并或分裂时,要注意的一点就是需要读取孩子节点的页到内存中,重新设置父节点的pageid

插入操作的分裂时机也可以是在maxsize+1时进行,实现方法是新创建一个maxsize+1大小的数组把原先节点的键值对copy后插入新的键值对进去,然后再分裂。(这样每个节点都能存满,我自己的实现就是这样的,但下面画的图是pair数量为maxsize时则发生分裂)

插入发生的场景分两种情况:

第一种普遍情况,发生分裂的节点不为根节点:

1.发生在叶节点中,同样把元素分到左右节点,然后key值需要插入到父节点中,对应value值为右节点pageid,右节点更新父节点指针;若父节点也已经满了插不进去,则需要递归调用插入父节点函数
2.发生在内部节点时,操作类似,不一样的地方在于中间key值不再放入右节点,只插入到父节点中,还有值得注意的一点是,原先节点(即左节点)中一半分配到右节点的孩子需要全部fetch出来后更新他们的parentpageid为右节点的id。

第二种发生分裂的节点为根节点,创建新内部节点,将新节点设为根节点,设置左右孩子,更新左右节点的parentpageid,然后:
1.原根节点为叶子节点,则平分pair放到左右两节点中,右节点第一个key同时也塞到父节点中;
2.原根节点为内部节点,分裂后取分到右边一半的第一对pair的key值移到新的根节点中,对应的value留在右节点中,同样的把分配到右节点的孩子全部fetch出来后更新parentpageid为右节点的id。

下面是出现两次分裂的情况(两次以上的分裂其实也是一样的):

​起初叶节点pair数量小于5在这里插入图片描述
插入H后发生了分裂。新节点需要修改父节点指针


插入父节点的操作导致父节点满了同样需要分裂
在这里插入图片描述

注意发生在内部节点的分裂,需要及时更新孩子的新父亲节点。
在这里插入图片描述

删除操作

如果节点中的键值对>=minsize时,不用进行合并;需要向兄弟节点借时,兄弟节点的键值对需满足>minsize。获取兄弟节点的方法则是通过父节点定位该节点的相邻兄弟,即value(指向左或右兄弟)和key值。

分两种情况:

兄弟够借。
考虑两种情况,这里n代表发生借/合并的节点,n’代表兄弟:

1.发生在叶子节点时,n为左,向右借,把key值拿过来后,注意把父节点中存放n’的一项的key值更新,n在右,向左借同理,需要把父节点指向n的一项的key值更新;
2.发生在内部节点时,n向n’借的做法是将父节点p上指向右兄弟节点的pair对的key值追加到节点n的元素队尾中,兄弟节点n’的第一个key值顶上去放到原来空缺的位置,第一个value再拼到节点n中;
右向左借同理,把父节点p上的key值插到到节点n的元素队头中,兄弟节点n’的最后一个key值顶上去替换,最后一个value拿到节点n的队头。

兄弟不够借,发生合并。

1.发生在叶子节点时。将两个节点的元素塞到左侧节点,如果发生合并的节点不是左侧节点那么需要将两个节点指针变量互换,目的是统一删除右节点(这样的好处是删除父节点中对应孩子的key和value时下标是一样的,方便父节点的整理);更新该节点指向下一叶子节点的指针,注意,若父节点删除对应的孩子元素后,若父节点元素数量也小于minsize时,需要递归调用本身。
这里用4阶b+树演示下:

在这里插入图片描述

2.发生在内部节点时。同样是统一删除右侧节点,所有元素移到左侧节点,删除右侧节点在父节点中对应的元素。注意,由于是内部节点,需要把孩子节点页读取出来,更新他们pageid为左侧节点。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值