参考:零声学院课程
一颗M阶B树T,满足以下条件
1. 每个结点至多拥有M棵子树
2. 根结点至少拥有两颗子树
3. 除了根结点以外,其余每个分支结点至少拥有M/2棵子树
4. 所有的叶结点都在同一层上
5. 有k课子树的分支结点则存在k-1个关键字,关键字按照递增顺序进行排序
6. 关键字数量满足ceil(M/2)-1 <= n <= M-1
B树通过分裂,得到新结点
扫描二维码关注公众号,回复:
12419123 查看本文章

B树通过合并,减少结点
新增key,都是加在叶子节点里;同时递归过程中需要判断子树key是不是M-1,并分裂子树
删除key,通过借或者合并,使得要删除的key落在叶子节点里;同时递归过程中需要判断子树key是不是<=ceil(m/2)-1,然后借或者合并子树
#include <stdio.h>
#include <stdlib.h>
/*
一颗M阶B树T,满足以下条件
1. 每个结点至多拥有M棵子树
2. 根结点至少拥有两颗子树
3. 除了根结点以外,其余每个分支结点至少拥有M/2棵子树
4. 所有的叶结点都在同一层上
5. 有k课子树的分支结点则存在k-1个关键字,关键字按照递增顺序进行排序
6. 关键字数量满足ceil(M/2)-1 <= n <= M-1
*/
#define ceil(M) ((M-1)/2)
typedef int KEY_VALUE;
struct btree_node{
KEY_VALUE *keys;
struct btree_node **children;
int num;
int leaf;//1 leaf ; 0 not leaf
};
struct btree_node* btree_node_create(int m,int leaf){
struct btree_node *node = malloc(sizeof(struct btree_node));
node->keys = malloc(sizeof(KEY_VALUE) * (m));//merge的时候,会出现刚好是m的情况
node->children = malloc(sizeof(struct btree_node*) * (m+1));
node->num = 0;
node->leaf = leaf;
int i;
for(i=0;i<m+1;i++)
node->children[i] = NULL;
return node;
}
void btree_node_destroy(struct btree_node *node){
free(node->keys);
free(node->children);
free(node);
}
typedef struct{
struct btree_node *root;
int m;//表示m阶
int ceil_m;
}btree;
btree* btree_create(int m){
btree *T = malloc(sizeof(btree));
T->root = btree_node_create(m,1);
T->m = m;
T->ceil_m = ceil(m);
return T;
}
void btree_split_child(btree* T,struct btree_node *node,int idx){
struct btree_node *x = node->children[idx];
struct btree_node *y = btree_node_create(T->m,x->leaf);
int i,j;
for(i=T->ceil_m+1,j=0;i<x->num;i++,j++){
y->keys[j] = x->keys[i];
}
for(i=T->ceil_m+1,j=0;i<=x->num;i++,j++){
y->children[j] = x->children[i];
}
y->num = x->num -T->ceil_m -1;
x->num = T->ceil_m;
for(i=node->num-1;i>=idx;i--){
node->keys[i+1] = node->keys[i];
}
node->keys[i+1] = x->keys[T->ceil_m];
for(i=node->num;i>=idx+1;i--){
node->children[i+1] = node->children[i];
}
node->children[i+1] = y;
node->num++;
}
void btree_insert_nonfull(btree *T,struct btree_node* node,KEY_VALUE key){
int i,j;
for(i=0;i<node->num&&key>node->keys[i];i++){}
if(i<node->num && key == node->keys[i]){
return;
}
if(node->leaf==1){
for(j=node->num-1;j>=i;j--){
node->keys[j+1] = node->keys[j];
}
node->keys[j+1] = key;
node->num++;
}else{
if(node->children[i]->num == T->m-1){
btree_split_child(T,node,i);
if(key == node->keys[i])
return;
else if(key > node->keys[i])
i++;
}
btree_insert_nonfull(T,node->children[i],key);
}
}
void btree_insert(btree* T,KEY_VALUE key){
if(T->root->num >= T->m-1){
struct btree_node *node = btree_node_create(T->m,0);
node->children[0] = T->root;
T->root = node;
btree_split_child(T,T->root,0);
}
btree_insert_nonfull(T,T->root,key);
}
void btree_merge(btree* T,struct btree_node *node,int idx){
struct btree_node *x = node->children[idx];
struct btree_node *y = node->children[idx+1];
int i,j;
x->keys[x->num] = node->keys[idx];
for(i=x->num+1,j=0;j<y->num;i++,j++){
x->keys[i] = y->keys[j];
}
for(i=x->num+1,j=0;j<=y->num;i++,j++){
x->children[i] = y->children[j];
}
x->num += (1 + y->num);
btree_node_destroy(y);
for(i=idx;i<node->num-1;i++){
node->keys[i] = node->keys[i+1];
}
for(i=idx+1;i<node->num;i++){
node->children[i] = node->children[i+1];
}
node->num--;
if(node->num == 0){
T->root = x;
btree_node_destroy(node);
}
}
void btree_delete_node(btree* T,struct btree_node *node, KEY_VALUE key){
if(node == NULL)
return;
int idx,i;
for(idx=0;idx<node->num&&key>node->keys[idx];idx++){}
if(idx<node->num && key == node->keys[idx]){
if(node->leaf == 1){
for(i=idx;i<node->num-1;i++){
node->keys[i] = node->keys[i+1];
}
node->num--;
if(node->num == 0){//root
}
return;
}else if(node->children[idx]->num > T->ceil_m){
struct btree_node *left = node->children[idx];
node->keys[idx] = left->keys[left->num-1];
btree_delete_node(T,left,left->keys[left->num-1]);
}else if(node->children[idx+1]->num > T->ceil_m){
struct btree_node *right = node->children[idx+1];
node->keys[idx] = right->keys[0];
btree_delete_node(T,right,right->keys[0]);
}else{
int flag = (node == T->root);
btree_merge(T,node,idx);
if(flag && node != T->root){
btree_delete_node(T,T->root,key);
}else{
btree_delete_node(T,node->children[idx],key);
}
}
}else{
struct btree_node *child = node->children[idx];
if(child == NULL){
return ;
}
if(child->num<= T->ceil_m){
struct btree_node *left=NULL,*right=NULL;
if(idx-1>=0)
left = node->children[idx-1];
if(idx+1<=node->num)
right = node->children[idx+1];
if(left != NULL && left->num > T->ceil_m ||
right != NULL && right->num > T->ceil_m){
int richR = 0;
if(right!=NULL)
richR = 1;
if(left!=NULL&&right!=NULL)
richR = right->num>left->num?1:0;
if(right!=NULL&&right->num>T->ceil_m&&richR){//borrow from right
child->keys[child->num] = node->keys[idx];
child->children[child->num+1] = right->children[0];
child->num++;
node->keys[idx] = right->keys[0];
for(i=0;i<right->num-1;i++){
right->keys[i] = right->keys[i+1];
}
for(i=0;i<right->num;i++){
right->children[i] = right->children[i+1];
}
right->num--;
}else{//borrow from left
for(i=child->num-1;i>=0;i--){
child->keys[i+1] = child->keys[i];
}
for(i=child->num;i>=0;i--){
child->children[i+1] = child->children[i];
}
child->keys[0] = node->keys[idx-1];
child->children[0] = left->children[left->num];
child->num++;
node->keys[idx-1] = left->keys[left->num-1];
left->num--;
}
}else if((left==NULL || left->num<=T->ceil_m) && (right==NULL || right->num<=T->ceil_m)){
if(left != NULL && left->num<=T->ceil_m){
btree_merge(T,node,idx-1);
child = left;
}else if(right!=NULL && right->num<=T->ceil_m){
btree_merge(T,node,idx);
}
}
}
btree_delete_node(T,child,key);
}
}
void btree_delete(btree* T,KEY_VALUE key){
btree_delete_node(T,T->root,key);
}
void btree_traverse(struct btree_node *node){
if(node == NULL)
return;
int i;
printf("[");
for(i=0;i<node->num;i++){
//btree_traverse(node->children[i]);
printf("%d, ",node->keys[i]);
}
printf("], ");
for(i=0;i<=node->num;i++){
btree_traverse(node->children[i]);
//printf("%d, ",node->keys[i]);
}
//btree_traverse(node->children[i]);
}
int main(){
btree *T = btree_create(5);
int i;
btree_insert(T,0);
btree_insert(T,1);
btree_insert(T,3);
btree_insert(T,4);
btree_insert(T,5);
btree_traverse(T->root);printf("\n");
btree_delete(T,2);
btree_traverse(T->root);printf("\n");
btree_delete(T,3);
btree_traverse(T->root);printf("\n");
btree_insert(T,2);
btree_traverse(T->root);printf("\n");
btree_insert(T,3);
btree_traverse(T->root);printf("\n");
btree_delete(T,5);
btree_traverse(T->root);printf("\n");
}