1 简介
B+树与B树相似, 也存在不同. 可以理解为把所有元素都放在叶子节点, 索引B树化的树.
B+树的一些性质:
1. B+树的节点分类: 内部节点(索引节点), 叶子节点. 如果只有根节点有元素, 那么其可以是内部节点也可以是叶子节点.
2. B+树与B树最大的不同是内部节点不保存数据, 只用与索引, 所有数据都放在叶子节点
3. 跟B树相同的性质: m阶B+树每个节点(包括叶子节点和内部节点)最多有m-1个关键字
4. 节点内部的key同B树相同, 也是从小到大排列, 对于内部节点的每个key, 其左树中的所有key都小于该key, 右树中的所有key都大于等于该key(注意是大于等于, 此处也是同B树的不同)
5. 每个叶子节点都存有相邻叶子节点的指针(双向链表)
2 增删操作
2.1 增加节点
跟B树相同的是, 插入元素也是必须要插入叶子节点, 如果被插入的叶子节点的key数量达到阶数, 叶子节点进行分裂, 然后中间的节点(索引为m / 2的, 从0开始)复制一份进入父节点(注意此处是与B树的不同, B树是移到父节点, 而不是复制). 当索引节点满了时, 就按照B树的方式, 移动到父节点.
举例说明:
1. 空的5阶B+树, 插入5:
2. 再插入8, 10, 15:
3. 插入16:
3.1 插入该节点
3.2 此时该节点达到了阶树5, 那么进行分裂, 索引(5 / 2 = 2)的节点(key为10)复制到父节点成为内部节点, 而子节点从该key进行分裂(该节点进入右边, 注意新的两个叶子节点要连起来):
4. 插入17:
5. 插入18
5.1 直接插入:
5.2 节点key数量达到了5, 裂开, 6复制进入父节点:
6. 插入一些数据后:
7. 插入7:
7.1 直接插入, 此时该节点key数量达到了阶数5:
7.2 裂开, 7进入父节点
7.3 父节点分裂, 此时不需要复制:
2.2 删除操作
首先就是在叶子节点中找到要删除的节点, 如果没有找到, 那么删除失败. 找到之后, 先把目标节点拿掉, 再看拿掉之后的节点key的数量, 如果大于ceil(m - 1) / 2 - 1(以后用最小key数量代替), 那么删除动作结束. 如果小于的话, 就需要进行接下来的操作. 如果该节点的兄弟节点key数量大于最小key数量, 那么就向其借一个key, 注意更新其索引节点的key. 如果兄弟节点key不大于最小key数量, 那么就将二者合并, 形成一个新的叶子节点, 并把两者的父节点中多余的key删除, 同时按照B树删除节点的方式递归向上删除.
举例说明:
1. 初始状态:
2. 删除22:
3. 删除15
3.1 拿掉15:
3.2 发现此时节点key数量小于最小key数量 --- 2, 其兄弟节点有3个key, 大于2, 那么向其借用一个9, 并更新其父索引节点的key:
4. 删除7
4.1 拿掉7:
4.2 其节点key小于2, 其兄弟节点key均为2, 没有大于2, 所以就合并其与兄弟节点, 并删除其父索引节点的key:
4.3 此时发现其父索引节点的key为1, 小于2, 那么就要按照B树的方式, 其兄弟节点为2, 没有大于2, 那么就将其父节点下移与该节点以及其兄弟节点合并: