b树的简单实现与基本操作(C语言)

这篇博客介绍了B树的基本概念、优势以及C语言实现B树插入操作的详细步骤。B树是一种针对磁盘存取优化的平衡查找树,每个节点可存储多个数据,减少磁盘存取次数,提供O(logN)的查找效率。文中还给出了B树的C语言代码实现,包括节点初始化、插入操作以及节点满时的分裂处理。
摘要由CSDN通过智能技术生成

今天上完数据结构课,想找找事情做,可本人又懒得刷题(爱好:躺平)。就没事找事看看书上的扩展内容,发现这个b树挺有难度,要是能实现也成就感满满了呀。那便话不多说,撸起袖子加油干。

b树的简单实现与基本操作(C语言)

b树

看了一篇博客,讲的是真滴好,推荐:
http://blog.csdn.net/v_JULY_v/article/details/6530142

B树定义

B树是专门为磁盘或其他直接存取的辅助存储设备设计的一类平衡查找树,可以实现O(logN)时间复杂度的存取操作。
不同于红黑树,B树的每个节点可以存放多个数据。根据每个节点存放数据的多少,可以把B树分为不同的阶数。

B树好处

B树查找数据速度快,和红黑树等平衡二叉查找树相当,同时由于B树的每个节点可以包含多个数据关键字,
相当于对数的底变大,查找的深度变小,减少了对磁盘的存取操作的次数。

B树性质

我们按照如下性质,来定义一棵非空的m阶B树(m>2,2阶B树相当于二叉平衡查找树):

每个非叶子节点中存放若干关键字数据,并且有若干指向儿子节点的指针。指针数目=关键字数目+1
根节点有最少1个,最多m-1个关键字,最少2个,最多m个子节点。
非根节点最少有[m/2](向上取整),最多m-1个关键字
每个节点中的关键字从左到右以非降序排列
每个关键字均不小于其左子节点的关键字,不大于其右子节点的所有关键字
每个叶子节点都具有相同的深度

C语言实现b树

#include<stdio.h>
#include<stdlib.h>

#define ORDER 3     //B树的阶数

typedef int KeyType;  //关键字数据类型
typedef struct BTNode	//B树结点
{
    int keynum;                        //结点中关键字的个数
    KeyType key[ORDER-1];                // 关键字数组,长度=阶数-1
    struct BTNode* child[ORDER];        // 孩子指针数组,长度=阶数
    int isLeaf;
    struct BTNode* parent;                 // 是否是叶子节点的标志

}BTNode,*BTree;

void BTree_init(BTNode **bt)//b树的初始化
{
    (*bt)=(BTNode*)malloc(sizeof(BTNode));
    (*bt)->isLeaf=1;
    (*bt)->keynum=0;
    (*bt)->parent=NULL;
}

void BTree_create(BTNode **tree,int length,int data[])//建立b树
{
    BTree_init(&(*tree));//初始化一个B树节点
    for(int i=0;i<length;i++)
    {

        BTree_insert(tree,data[i]);
    }
}

///以下为插入环节

int isfull(BTNode *node)//判断节点是否是满节点
{
    if(node->keynum < ORDER)
    {
        return 0;
    }
    else
    {
        return 1;
    }
}

void BTree_insert(BTree *tree,KeyType key)//b树插入
{
    BTNode *bnp = *tree;
    //节点满,直接进行分裂
    if(isfull(*tree))
    {
        split_tree(tree);
        BTree_insert(tree,key);
        return;
    }
    //是叶子节点且不满,直接插入
    if(bnp->isLeaf && !isfull(bnp))
    {
        //比最大的关键字都大,直接插在末尾
        if(key>=bnp->key[bnp->keynum -1])
        {
            bnp->keynum++;
            bnp->key[bnp->keynum-1] = key;
        }
        else
        {
            for(int i = 0;i<ORDER-1;i++)
            {
                //找到一个比待插入关键字大的关键字,则直接插入
                if(key< bnp->key[i] )
                {
                    KeyType  temp= bnp->key[i];
                    bnp->key[i] = key;
                    bnp->keynum++;
                    for(int j = i + 1;j< bnp->keynum;j++)
                    {
                        key = bnp->key[j];
                        bnp->key[j] = temp;
                        temp = key;
                    }

                    break;
                }
            }
        }
        return;
    }
    //不是叶子节点,查找对应的子树,递归插入
    if(!bnp->isLeaf)
    {
        for(int i = 0;i < bnp ->keynum;i++)
        {
            if(key<bnp->key[i])
            {
                BTree_insert(&((*tree)->child[i]),key);
                return;
            }
        }
        BTree_insert(&((*tree)->child[bnp->keynum]),key);
    }
}

void split_tree(BTree *tree)//子树分裂
{
    BTree bnp1 = *tree;
    BTree bnp2;
    BTree_init(&(bnp2));
    BTree bp;
    int num = bnp1->keynum;
    int split = num/2;
    if(bnp1->parent == NULL)
    {
         BTree_init(&(bp));
         bp->parent = NULL;
         bp->keynum = 1;
         bp->isLeaf = 0;
         bp->key[0] = bnp1->key[split];
         bp->child[0] = bnp1;
         bp->child[1] = bnp2;
    }
    else
    {
        bp = bnp1->parent;
        bp->isLeaf = 0;
        bp->keynum++;
        KeyType temp1, temp2;
        BTNode *tcp1, *tcp2;
        for(int i = 0;i < bp->keynum;i++)
        {
            //新关键字插到末尾
            if(i == bp->keynum-1)
            {
                bp->key[i] = bnp1->key[split];
                bp->child[i] = bnp1;
                bp->child[i+1] = bnp2;
                break;
            }
            //新关键字插到中间
            if(bp->key[i]>bnp1->key[split])
            {
                tcp2 = bnp2;
                temp2 = bnp1->key[split];
                for(int k = i;k<bp->keynum;k++)
                {
                    //关键字后移
                    temp1 = bp->key[k];
                    bp->key[k] = temp2;
                    temp2 = temp1;
                    //子树指针后移
                    tcp1 = bp->child[k+1];
                    bp->child[k+1] = tcp2;
                    tcp2 = tcp1;
                }
            }

        }
    }

    bnp1->keynum = split;
    bnp2->keynum = num - split -1;
    for(int i = 0, j = split+1;j<num;j++)
    {
        bnp2->key[i]=bnp1->key[j];
        bnp2->child[i]=bnp1->child[j];
    }
    bnp2->child[bnp2->keynum] = NULL;
    bnp2->isLeaf = bnp1->isLeaf;
    bnp2->parent = bp;
    bnp1->parent = bp;

    (*tree) = bp;
}

大体实现b树的插入,待进一步功能实现,今天先搞到这,有时间再完善。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mcl19909949541

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值