一 插入
- 无根节点
当没有根结点时,操作相当简单,只是从存储空间中申请一个新结点,然后设置该结点的prev,next,is_inner,然后将要插入的数据插入该结点。
void insert(const t_var& key, t_val v)
{
//没有元素,创建一个叶子结点,新数据插入并返回
if (hdb->root_id == 0)
{
//创建结点,插入新数据并将根结点设置为该结点。
hdb->root_id = create_node(0, 0, 0, { {key.val,v} }).id();
//同步根结点数据
flush_member(hdb, root_id);
//插入完成,返回
return;
}
- 有根结点
- 生成查询路径
b+树是一个自底向上插入的算法,所以我们在插入时,得先找到key需要插入到的路径。基本上就是结点及要插入位置的组合。由于可能插入的位置可能在最前方,超过了b+树所覆盖的范围,所以找到的结点位置可能为-1,增加一个self_pos以方便操作(其实不加也可以,可以通过sub_pos计算出来)。
- 生成查询路径
auto root = map_node(hdb->root_id);
//生成路径
struct t_path
{
t_auto_node node;
int32_t self_pos;
int32_t sub_pos;
};
std::vector<t_path>paths;
{
int32_t self_pos = -1;
auto node = root;
while (true)
{
auto sub_pos = node->find_range(key);
paths.push_back({ node,self_pos,sub_pos });
if (node->is_inner == 0)
break;
self_pos = sub_pos >= 0 ? sub_pos : 0;
node = map_node(node->at(self_pos).val);
}
}
2. 自底向上循环插入
1. node还有空间
2. 可插入prev
3. 可插入next
4. 无法插入,只能分裂
3. 生成新根结点
二 删除
- 无根结点
- 有根结点
- 生成查询路径
- 自底向上循环删除
- node数量足够
- 可向prev借数据
- 可向next借数据
- 可合并到prev
- 可合并到next
- 根节点塌缩
【未完待续】