B-树浅实现

B-树查找特定元素e

1.假设当前在树t当中查找元素e

2.同二叉搜索树类似,先在根结点的key数组中找到e<=key[i]的位置i

3.当t不为空

​ (1)如果e==key[i],则找到元素,返回查找结果

​ (2)如果e<key,则在key[i]的左子树也就是ptr[i]当中继续查找,将当前根节点记为t0,将根节点置为ptr[i],回到1。

4.当t为空,则未找到元素,插入位置为t0节点、第i个位置

B-树插入元素e

1.利用查找算法找到插入的节点p和位置i,ap初始为NULL,指向比e大的节点

2.将元素e和ap插入相应节点p,然后判断p的key数量是否超过允许的最大结点数M

(1)如果未超过,则完成插入

(2)如果超过,则进行分裂,也就是将p当中的key拆分成一棵树:

​ a.令s= ⌈ M ⌉ \lceil M\rceil M-1

​ b.key[s]作为根节点,然后新建一个新节点ap,将p当中key|s+1:M|的所有key和ptr|s+1:M|的所有ptr都移动到ap当中

​ c.将ap的父亲指针置为p的父指针

​ d.令p=p->parent,e=p->key[s],

(3)如果此时p不为空也就是根节点并没有分裂,则回到2,将新分裂的key[s]和其右指针ap插入到原本p所在的节点当中;反之,进入4

4.生成新的根节点,元素e作为唯一一个元素,左指针为原来树根t,右子树为新分裂的ap

B-树删除元素e

1.首先查找删除元素e的节点位置p和位置i

2.然后判断是否为叶子节点、

(1)如果是叶子节点,直接删除,然后判断删除后该节点元素的个数是否小于规定最小值m

​ a.如果没有,结束删除

​ b.如果小于规定最小值m,则进行调整

(2)如果非叶子节点,则从从左子树取出左子树最大值lm,将需要删除的e所在key[i]置为lm,递归调用本删除算法从左子树删除lm

B-树删除调整

1.如果需要调整的节点p不为根节点

(1)通过父指针q找到p在q->ptr数组的位置j

(2)判断p的位置

​ a.p为q的最左侧子节点

​ 判断p的右兄弟rp的key的个数是否大于m,

​ 如果大于,则将右兄弟最小的key替换为其父亲key,父亲key指的是q->key数组当中满足key>p当中所有节点的最小的key值,然后将父亲key插入到p当中

​ 如果小于,则将父亲key和右兄弟合并到p当中,然后删除q当中的父亲key和其右指针(也就是右兄弟)

​ b.p为q中间子节点

​ 判断p的右兄弟rp的key的个数是否大于m

​ 如果大于,则将右兄弟最小的key替换为其父亲key,然后将父亲key插入到p当中

​ 如果小于,判断左兄弟lp的key个数是否大于m,同样右兄弟类似的操作

​ 如果lp和rp的key个数都不够,则将父亲key和右兄弟合并到p当中,然后删除q当中的父亲key和其右指针(也就是右兄弟)

​ c.p为q最右侧子节点

​ 判断p的左兄弟rp的key的个数是否大于m

​ 如果大于,左兄弟的最大值替换父亲key,然后将父亲key插入到p当中

​ 如果小于,则将父亲key和右兄弟合并到p当中,然后删除q当中的父亲key和其右指针(也就是右兄弟)

#include <iostream>
#include <queue>
#include <vector>

using namespace std;
#define MAXM 10

const int m=4;  //阶数
const int Max_key=m-1; //最大关键字个数
const int Min_key=(m-1)/2;//最小关键字个数
typedef int KeyType;//关键字类型
const int unknown=99999;

typedef struct Node
{
    int keynum;//结点个数
    struct Node *parent;//父节点
    KeyType key[MAXM];//关键字向量,0号多元未使用
    struct Node *ptr[MAXM];//子树指针向量
    //记录指针向量
    Node()
    {
        keynum=0;
        parent=NULL;
        for(int i=0;i<MAXM;i++)
        {
            key[i]=unknown;
            ptr[i]=NULL;
        }
    }
}BTNode,*BTree;

typedef struct
{
    BTNode *pt;//找到的结点
    int i;//查找结果在节点中关键字的位置
    int tag;//查找是否成功
}Result;

typedef enum status
{
    FALSE,
    TRUE,
    OK,
    ERROR,
    OVERFLOW,
    EMPTY
}Status;

Status InitBTree(BTree &t);//初始化B树
Status InsertNode(BTree t,KeyType key,BTree ap,int i);//插入特定结点
Status InsertBtree(BTree &t,BTree q,int i,KeyType key);//插入关键字
Result SearchBtree(BTree t,KeyType key);//查找关键字
int Search(BTree t,int key);//返回关键字在结点当中的位置
Status DeleteNode(BTree p,int i);//从结点当中删除关键字
Status DeleteBtree(BTree t,KeyType key);//删除关键字

Status InitBTree(BTree &t)
{
    t=NULL;
    return OK;
}

int Search(BTree t,int key)
{
    int i;
    for(i=1;i<=t->keynum;i++)
    {
        if(t->key[i]>=key)
            break;
    }
    return i;
}
Status InsertNode(BTree t,KeyType key,BTree ap,int i)
{
    int j=t->keynum;
    while(j>=i)
    {
        t->ptr[j+1]=t->ptr[j];
        t->key[j+1]=t->key[j];
        j--;
    }
    t->ptr[i]=ap;
    t->key[i]=key;
    t->keynum++;
    return OK;
}//插入key[i]和ptr[i]

void SplitNode(BTree p,int s,BTree &ap)
{
    ap=new BTNode;
    int j=0;
    ap->ptr[j++]=p->ptr[s];
    if(ap->ptr[0])
        ap->ptr[0]->parent=ap;
    p->ptr[s]=NULL;
    p->key[s]=unknown;
    for(int i=s+1;i<=p->keynum;i++)
    {
        ap->key[j]=p->key[i];
        ap->ptr[j]=p->ptr[i];
        if(ap->ptr[j])
            ap->ptr[j]->parent=ap;
        p->ptr[i]=NULL;
        p->key[i]=unknown;
        j++;
    }
    ap->keynum=p->keynum-s;
}


Status InsertBtree(BTree &t,BTree q,int i,KeyType key)
{
    KeyType x=key;
    BTree ap=NULL;
    bool finished=FALSE;
    while(q&&!finished)
    {
        InsertNode(q,x,ap,i);
        if(q->keynum<=Max_key)
        {
            finished=TRUE;
        }
        else
        {
            int mid=(Max_key+1)/2;
            x=q->key[mid];
            SplitNode(q,mid,ap);//将key[mid,m]和ptr[mid+1,m]转移到ap
            ap->parent=q->parent;
            q->keynum=mid-1;
            q=q->parent;
            if(q)
            {
                i=Search(q,x);
            }
        }
    }
    if(!finished)
    {
        //cout<<"insert root"<<endl;
        BTree nt=new BTNode;
        nt->keynum=1;
        nt->key[1]=x;
        nt->ptr[0]=t;
        nt->ptr[1]=ap;
        if(t)
            t->parent=nt;
        if(ap)
            ap->parent=nt;
        t=nt;
    }
    return OK;
}

Result SearchBtree(BTree t,KeyType key)
{
    BTree q,p;
    int flag=0;
    q=t;
    p=q;
    int i=1;
    while(q&&!flag)
    {
        i=Search(q,key);
        if(q->key[i]==key)
            flag=1;
        else
        {
            p=q;
            q=q->ptr[i-1];
        }
    }
    Result r;
    if(flag)
    {
        r.i=i;
        r.tag=1;
        r.pt=q;
    }
    else
    {
        r.i=i;
        r.pt=p;
        r.tag=0;
    }
    return r;
}

Status DeleteNode(BTree p,int i)
{
    for(;i<p->keynum;i++)
    {
        p->key[i]=p->key[i+1];
        p->ptr[i]=p->ptr[i+1];
    }
    p->key[i]=unknown;
    delete (p->ptr[i]);
    p->ptr[i]=NULL;
    p->keynum--;
    return OK;
}

Status MoveLeft(BTree lp,BTree rp)
{
    int i=lp->keynum+1;
    int j=1;
    while(j<=rp->keynum)
    {
        lp->key[i]=rp->key[j];
        lp->ptr[i]=rp->ptr[j];
        rp->key[j]=unknown;
        rp->ptr[j]=NULL;
        i++;
        j++;
        lp->keynum++;
    }
}
Status AdjustBtree(BTree &t,BTree p)
{
    //不为根节点
    if(p->parent)
    {
        BTree q=p->parent;
        BTree lp=NULL;
        BTree rp=NULL;
        int j=0;
        for(;j<=q->keynum;j++)
        {
            if(q->ptr[j]==p)
                break;
        }
        if(j==0)
        {
            rp=q->ptr[j+1];
            if(rp->keynum>Min_key)
            {
                InsertNode(p,q->key[j+1],rp->ptr[0],p->keynum+1);
                q->key[j+1]=rp->key[1];
                DeleteNode(rp,1);
            }
            else
            {
                InsertNode(p,q->key[j+1],rp->ptr[0],p->keynum+1);
                MoveLeft(p,rp);
                DeleteNode(q,j+1);
                rp=NULL;
            }
        }//p为最左边指针
        else if(j>0&&j<q->keynum)
        {
            lp=q->ptr[j-1];
            rp=q->ptr[j+1];
            if(rp->keynum>Min_key)
            {
                InsertNode(p,q->key[j+1],rp->ptr[0],p->keynum+1);
                q->key[j+1]=rp->key[1];
                DeleteNode(rp,1);
            }
            else if(lp->keynum>Min_key)
            {
                InsertNode(p,q->key[j],lp->ptr[lp->keynum],1);
                q->key[j]=lp->key[lp->keynum];
                DeleteNode(lp,lp->keynum);
            }
            else
            {
                InsertNode(p,q->key[j+1],rp->ptr[0],p->keynum+1);
                MoveLeft(p,rp);
                DeleteNode(q,j+1);
                rp=NULL;
            }
        }//中间指针
        else
        {
            lp=q->ptr[j-1];
            if(lp->keynum>Min_key)
            {
                InsertNode(p,q->key[j],lp->ptr[lp->keynum],1);
                q->key[j]=lp->key[lp->keynum];
                DeleteNode(lp,lp->keynum);
            }
            else
            {
                InsertNode(lp,q->key[j],p->ptr[0],lp->keynum+1);
                MoveLeft(lp,p);
                DeleteNode(q,j);
                p=NULL;
            }
        }//最右边指针
        if(q->keynum<Min_key)
        {
            AdjustBtree(t,q);
        }
    }
    else
    {
        t=t->ptr[0];
        /*
        if(t->ptr[0])
            cout<<t->ptr[0]->key[1]<<endl;*/
    }
}
Status DeleteBtree(BTree t,KeyType key)
{
    Result r=SearchBtree(t,key);
    if(!r.pt)
        return ERROR;
    BTree p=r.pt;
    BTree temp;
    temp=p->ptr[0];
    if(temp==NULL)
    {
            DeleteNode(p,r.i);
            if(p->keynum<Min_key)
                AdjustBtree(t,p);
    }//叶子结点
    else
    {
        BTree lc=p->ptr[r.i-1];//如果还有左孩子,则从左孩子当中找个最大值替代要删除的key
        p->key[r.i]=lc->key[lc->keynum];
        DeleteBtree(lc,lc->key[lc->keynum]);
    }

    if(t->keynum==0)
    {
        BTree t1=t->ptr[0];
        t=t->ptr[0];
        t->ptr[0]=NULL;
    }
}

void DisplayBTree(BTree t)
{
    queue<BTNode*> q;
    q.push(t);
    vector<vector<vector<int>>> res;
    q.push(NULL);
    BTree p;
    vector<vector<int>> t2;
    while(!q.empty())
    {
        p=q.front();
        q.pop();
        if(!p)
        {
            res.push_back(t2);
            if(!q.empty())
            {
                q.push(NULL);
            }
            t2.clear();
        }
        else
        {
            vector<int> t1;
            for(int i=0;i<=p->keynum;i++)
            {
                if(p->ptr[i])
                    q.push(p->ptr[i]);
            }
            for(int i=1;i<=p->keynum;i++)
            {
                t1.push_back(p->key[i]);
            }
            t2.push_back(t1);
        }
    }
    for(int i=0;i<res.size();i++)
    {
        for(int j=0;j<res[i].size();j++)
        {
            for(int k=0;k<res[i][j].size();k++)
            {
                cout<<res[i][j][k]<<' ';
            }
            cout<<"---";
        }
        cout<<endl;
    }
}
int main()
{
    BTree t;
    InitBTree(t);
    vector<int> testData={56,3,37,24,53,90,61,100,70,45,77,33,1000,1500,2600,26};
    for(int i=0;i<testData.size();i++)
    {
        Result r=SearchBtree(t,testData[i]);
        if(r.tag==0)
            InsertBtree(t,r.pt,r.i,testData[i]);
         //DisplayBTree(t);
    }
    DisplayBTree(t);
    DeleteBtree(t,100);
    DisplayBTree(t);
    DeleteBtree(t,1000);
    DisplayBTree(t);
    DeleteBtree(t,1500);
    DisplayBTree(t);
    DeleteBtree(t,24);
    DisplayBTree(t);
    DeleteBtree(t,2600);
    DisplayBTree(t);
    DeleteBtree(t,90);
    DisplayBTree(t);
    DeleteBtree(t,56);
    DisplayBTree(t);
    DeleteBtree(t,77);
    DisplayBTree(t);
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值