实现
#include <iostream>
using namespace std;
//定义B树节点
struct BTree
{
//关键字个数
int number;
//指向孩子数组的二级指针
BTree **childrens;
//是否是叶子节点
bool leafnode;
//指向关键字数组的二级指针
int *key;
//最小度数
int t;
};
//创建节点并且初始化
BTree *creat_node(){
BTree *root = new BTree;
root->leafnode = true;
root->number = 0;
root->t = 2;
root->key = new int[2*root->t];
root->childrens = new BTree*[2*root->t+1];
// root->childrens = new BTree*;
return root;
}
//遍历输出
void btree_traverse(BTree *root){
//叶子节点
if (root->leafnode == true)
{
for(int i = 1;i <= root->number;i++)
{
cout<<root->key[i];
}
}
else
{
for (int i = 1; i <= root->number; i++)
{
btree_traverse(root->childrens[i]);
cout<<root->key[i];
}
btree_traverse(root->childrens[root->number+1]);
}
}
//将节点x的第i个满子节点按照中间关键字进行分裂
void btree_splite(BTree *x, int i){
//新的节点
BTree *newnode = creat_node();
//节点x的第i个满子节点y
BTree *y = x->childrens[i];
//新节点初始化
newnode->number = x->t-1;
newnode->leafnode = y->leafnode;
if (y->leafnode != true)
{
int j = 1;
int k;
for (k = x->t+1; k <=2*x->t-1; k++)
{
newnode->childrens[j] = y->childrens[k];
newnode->key[j] = y->key[k];
j++;
}
newnode->childrens[j] = y->childrens[k];
}
else
{
int j = 1;
int k;
for (k = x->t+1; k <=2*(x->t)-1; k++)
{
newnode->key[j] = y->key[k];
j++;
}
}
//将节点y的第t个位置的节点上升到节点x中
for (int j = x->number ; j >= i; j--)
{
x->key[j+1] = x->key[j];
}
x->key[i] = y->key[y->t];
//更新节点y中关键字个数
y->number = y->t - 1;
//更新节点x的孩子数组
for (int j = x->number+1; j > i; j--)
{
x->childrens[j+1] = x->childrens[j];
}
x->childrens[i+1] = newnode;
//更新节点x的关键字个数
x->number += 1;
}
//插入关键字
void btree_insert(BTree **root ,int x){
//假如根节点是满节点
if ((*root)->number == 2 * (*root)->t - 1)
{
//创建一个节点,作为新的根节点
BTree *newnode = creat_node();
newnode->childrens[1] = *root;
newnode->leafnode = false;
newnode->number = 0;
//更新根节点
*root = newnode;
//将根节点的第一个满子节点裂开
btree_splite(*root,1);
//测试
// btree_traverse(*root);
}
//假如节点root为叶子节点
if ((*root)->leafnode == true)
{
//插入位置
int i = (*root)->number;
//调整插入位置
while (i > 0 && (*root)->key[i] > x)
{
(*root)->key[i+1] = (*root)->key[i];
i = i - 1;
}
//将x插入
(*root)->key[i+1] = x;
//更新关键子个数
(*root)->number += 1;
}
else
{
//寻找比关键字x小的关键字
int i = (*root)->number;
while (i > 0 && (*root)->key[i] >x)
{
i = i - 1;
}
if ((*root)->childrens[i+1]->number == 2*((*root)->t)-1)
{
btree_splite((*root),i+1);
//再次调整i的值
i = (*root)->number;
while (i > 0 && (*root)->key[i] >x)
{
i = i - 1;
}
//测试
// btree_traverse(*root);
}
//测试
// btree_traverse(*root);
if ((*root)->childrens[i+1] == NULL)
{
(*root)->childrens[i+1] = new BTree;
cout<<"haha "<<endl;
}
//测试
// if (x != 9)
// {
// btree_insert(&((*root)->childrens[i+1]),x);
// }
btree_insert(&((*root)->childrens[i+1]),x);
}
}
//是否有关键值 有关键值的话返回关键值所在节点的指针
BTree *search(BTree *x,int key){
if (x->number == 0)
{
return NULL;
}
int i = 1;
while(x->key[i]<key && i<=x->number )
{
i++;
}
if (i<=x->number && x->key[i] == key)
{
// cout<<x->number<<endl;
return x;
}
else
{
if (x->leafnode == true)
{
return NULL;
}
else
{
//test
// cout<<x->key[1]<<endl;
// cout<<x->number<<endl;
// cout<<x->leafnode<<endl;
x = x->childrens[i];
//测试
// cout<<x->key[1]<<endl;
// cout<<x->key[2]<<endl;
// cout<<x->number<<endl;
// cout<<x->leafnode<<endl;
x = search(x,key);
return x;
}
}
}
//delete
BTree *btree_delete_key(BTree *root, BTree *x, int key){
// 假如以x为根的子树中没有key
if (!search(x,key))
{
cout<<"该关键值不存在";
return root;
}
else
{
//关键值key所在节点
x = search(x,key);
//test
// cout<<x->number<<endl;
// cout<<x->key[1]<<endl;
// cout<<x->leafnode<<endl;
// 在节点x上找到了与key值相等的位置
int i;
for (i = 1; x->key[i]<key && i <= x->number; i++);
//假如节点x为叶子节点
if (x->leafnode)
{
//删除
for (int j = i; j < x->number; j++)
{
x->key[j] = x->key[j+1];
}
x->number--;
}
//假如节点x不是叶子节点
else
{
//左孩子节点
BTree *left = x->childrens[i];
//假如key的左子孩子的所在节点关键值个数大于等于t
if (left->number >= x->t)
{
//前驱
int front;
//在左孩子节点上寻找key的前驱
front = left->key[left->number];
//前驱 key 互换位置
left->key[left->number] = key;
x->key[i] = front;
//递归
btree_delete_key(root,left,key);
}
//右子孩子节点
BTree *right = x->childrens[i+1];
//假如key的右子孩子的所在节点的关键值个数大于等于t
if (right->number >= x->t)
{
//后继
int back = x->key[1];
//后继 key 互换位置
right->key[1] = key;
x->key[i] = back;
//递归
btree_delete_key(root,right,key);
}
//假如key的左子孩子与右子孩子节点的关键值个数都=t-1
else
{
//将右子孩子节点中的关键值以及孩子节点 key合并至左孩子节点
left->key[left->number+1] = key;
for (int j = 1; j <= right->number; j++)
{
left->key[left->number+1+j] = right->key[j];
}
for (int j = 1; j <= right->number+1; j++)
{
left->childrens[left->number+j+1] = right->childrens[j];
}
left->number += right->number+1;
//释放右孩子节点
delete right;
//删除节点x中的key
for (int j = i; j <= x->number; j++)
{
x->key[j] = x->key[j+1];
x->childrens[j+1] = x->childrens[j+2];
}
x->number--;
//递归
btree_delete_key(root,left,key);
}
}
}
}
int main()
{
//创建根节点
BTree *root = creat_node();
//要插入的数组
int array[] = {1,2,3,4,5,6,7,8,9,10};
// int array[] = {1,2,3,4};
// 插入
for (int i = 0; i < sizeof(array)/sizeof(int); i++)
{
btree_insert(&root,array[i]);
}
//测试
// root->key[1] = 1;
// cout<<root->number<<endl;;
// cout<<sizeof(array)/sizeof(int);
// btree_insert(&root,4);
// cout<<root->childrens[1]->key[3]<<endl;
// cout<<root->key[2]<<endl;
// cout<<root->childrens[2]->childrens[3]->number<<endl;
// cout<<root->childrens[2]->childrens[3]->leafnode<<endl;
// cout<<root->childrens[2]->key[2]<<endl;
// btree_traverse(root->childrens[3]);
//遍历输出
// btree_traverse(root);
//删除
btree_delete_key(root,root,3);
//遍历输出
btree_traverse(root);
}
当然我们这里的最小度数为2,假如需要最小度数为其他数值的B树的话只需要将代码中的最小度数t从2变为需要的数值就好。