B树的性质
一颗M阶B树T,满足以下条件
1.每个节点至多拥有M颗子树
2.根节点至少拥有两颗子树
3.除了根节点以外,其余每个分支结点至少拥有M/2颗子树
4. 所有的叶节点都在同一层上
5. 有k颗子树的分支结点则存在k-1个关键字,关键字按照递增顺序进行排序
6. 每个非根节点所包含的关键字数量满足ceil(M/2)-1 <= n <= M-1
B树的作用
磁盘存储,是采用B树的结构。磁盘的一个扇区,相当于B树的一个节点。使用B树,存储的层数降低了,使得查找性能的效率提升了。
B树的添加
1.先判断结点里的关键字数量是否等于M-1了
2.如果是的话,分裂
两种情况:
1) 如果分裂的是根节点,那么1节点分裂成3节点
2) 如果不是,那么1节点分裂成2节点
3.如果不是的,对结点的Key进行对比,找到合适的位置
btree_node *btree_create_node(int leaf) {
btree_node *node = (btree_node*)calloc(1, sizeof(btree_node));
if (node == NULL) assert(0);
node->leaf = leaf;
node->keys = (KEY_VALUE*)calloc(1, (M-1)*sizeof(KEY_VALUE));
node->childrens = (btree_node**)calloc(1, M * sizeof(btree_node));
node->num = 0;
return node;
}
// 对插入的节点,进行分裂
void btree_split_child(btree *T, btree_node *x, int i) {
int t = T->t;
btree_node *y = x->childrens[i];
btree_node *z = btree_create_node(t, y->leaf);
z->num = t - 1;
int j = 0;
for (j = 0;j < t-1;j ++) {
z->keys[j] = y->keys[j+t];
}
if (y->leaf == 0) {
for (j = 0;j < t;j ++) {
z->childrens[j] = y->childrens[j+t];
}
}
y->num = t - 1;
for (j = x->num;j >= i+1;j --) {
x->childrens[j+1] = x->childrens[j];
}
x->childrens[i+1] = z;
for (j = x->num-1;j >= i;j --) {
x->keys[j+1] = x->keys[j];
}
x->keys[i] = y->keys[t-1];
x->num += 1;
}
void btree_insert(btree *T, KEY_VALUE key) {
btree_node *r = T->root;
// M 指M阶的B树
if (r->num == M - 1) {
btree_node *node = btree_create_node(M, 0);
T->root = node;
node->childrens[0] = r;
btree_split_child(T, node, 0);
int i = 0;
if (node->keys[0] < key) i++;
btree_insert_nonfull(T, node->childrens[i], key);
} else {
btree_insert_nonfull(T, r, key);
}
}
// 将要插入的节点没有满,直接插入
void btree_insert_nonfull(btree *T, btree_node *x, KEY_VALUE k) {
int i = x->num - 1;
if (x->leaf == 1) {
// 对于叶节点,只需要找到合适的位置,把原来的有数据依次往后挪一位,再把数据插入
while (i >= 0 && x->keys[i] > k) {
x->keys[i+1] = x->keys[i];
i --;
}
x->keys[i+1] = k;
x->num += 1;
} else {
// 对于非叶子节点,先找到合适的位置,再判断它的孩子节点满了没有,满了先分裂再插入,没满继续往下层节点递归寻找
while (i >= 0 && x->keys[i] > k) i --;
if (x->childrens[i+1]->num == M-1) {
btree_split_child(T, x, i+1);
if (k > x->keys[i+1]) i++;
}
btree_insert_nonfull(T, x->childrens[i+1], k);
}
}
B树与B+树的区别?
-
B+树中只有叶子节点会带有指向数据记录的指针(ROWID),而B树则所有节点都带有,在内部节点出现的索引项不会再出现在叶子节点中。
-
B+树中所有叶子节点都是通过指针连接在一起,而B树不会。
B+树的优点:
-
非叶子节点不会带上ROWID,这样,一个块中可以容纳更多的索引项,一是可以降低树的高度。二是一个内部节点可以定位更多的叶子节点。
-
叶子节点之间通过指针来连接,范围扫描将十分简单,而对于B树来说,则需要在叶子节点和内部节点不停的往返移动。
B树的优点:
对于在内部节点的数据,可直接得到,不必根据叶子节点来定位。