B树的插入与删除

实现

#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变为需要的数值就好。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值