B树
B树的定义
- 多叉搜索树,每个节点最多有M个子树,M-1个关键字
- 根节点若非唯一节点,则最少有2个子树,即最少有1个关键字
- 非根节点也非叶子节点的,最少有ceil(M/2)个子树,ceil(M/2)-1个关键字
- 叶子节点都在树的同一层
- 每个节点的关键字从小到大排列,充当划分子树的边界
c
// B树的结构体如下:
typedef struct _btree_node {
int *keys;
struct _btree_node **childrens;
int num; // 有多少个关键字
int leaf; // 是否是叶子节点
} btree_node;
typedef struct _btree {
struct _btree_node *root;
int t; // ceil(M/2)-1,方便B树的分裂和合并操作
} btree;
B树的节点生成和销毁
c
btree_node *btree_node_create(int t, int leaf)
{
btree_node *node = calloc(1, sizeof(btree_node ));
node->keys= calloc(2*t-1, sizeof(int));
node->childrens = calloc(2*t, sizeof(btree_node *));
node->num = 0;
node->leaf = leaf;
return node;
}
void btree_node_destroy(btree_node *node)
{
free(node->keys);
free(node->childrens);
free(node);
}
B树的分裂
c
void btree_split_child(btree *T, btree_node *x, int idx) {
btree_node *y = x->childrens[idx];
int t = T->t;
btree_node *z = btree_node_create(t, y->leaf);
for (int i = 0; i < t - 1; i++) {
z->keys[i] = y->keys[i+t];
}
if (y->leaf == 0) {
for (int i = 0; i < t; i++) {
z->childrens[i] = y->chiledrens[i+t];
}
}
z->num = t - 1;
y->num = t - 1;
for (int i = x->num; i > idx; i--) {
x->keys[i] = x->keys[i-1];
x->childrens[i+1] = x->childrens[i];
}
x->keys[idx] = y->keys[t-1];
x->childrens[idx+1] = z;
x->num += 1;
}
B树的合并
c
void btree_merge(btree *T, btree_node *x, int idx) {
btree_node *y = x->childrens[idx];
btree_node *z = x->childrens[idx+1];
int t = T->t;
for (int i = 0; i < t - 1; i++) {
y->keys[i+t] = z->keys[i];
}
y->keys[t - 1] = x->keys[idx];
if (z->leaf == 0) {
for (int i = 0; i < t; i++) {
y->childrens[i+t] = z->childrens[i];
}
}
y->num += t;
btree_node_destroy(z);
for (int i = idx + 1; i < x->num; i++) {
x->keys[i-1] = x->keys[i];
x->childrens[i] = x->childrens[i+1];
}
x->num -= 1;
}