算法导论18(B树)

插入
BTreeInsert(node *&root,char k)的工作原理
若root是一个满结点,分配一个空结点tmp,让root成为tmp的孩子,让tmp成为新的root,调用BTreeSplitChild(root,1),调用BTreeInsertNonfull(root,k);否则,直接调用BTreeInsertNonfull(root,k)。

BTreeSplitChild(node *x,int i)的工作原理
//x是一个非满结点,x->c[i]是一个满结点
x->c[i]分裂,x->c[i]的中间结点升至x。

BTreeInsertNonfull(node *x,char k)的工作原理
//x是一个非满结点
(1)x是叶结点:
直接将k插入x
(2)x是内部结点:
若x->c[i]是一个满结点,调用BTreeSplitChild(x,i),递归调用BTreeInsertNonfull(x->c[i],k);否则,直接递归调用BTreeInsertNonfull(x->c[i],k)。

删除
BTreeInsert(node *&root,char k)的工作原理
若root只包含一个关键字,root是内部结点,且root->c[1]和root->c[2]都只包含t-1个关键字,调用BTreeMergeChild(root,1),删除root,让root->c[1]成为新的root,调用BTreeDeleteNonempty(root,k);否则,直接调用BTreeDeleteNonempty(root,k)。

BTreeMergeChild(node *x,int i)的工作原理
//x至少包含t个关键字,x->c[i]和x->c[i+1]都只包含t-1个关键字
把x->key[i]和x->c[i+1]合并进x->c[i],删除x中的x->key[i],删除x->c[i+1]。

BTreeInsertNonempty(node *x,char k)的工作原理
//x至少包含t个关键字
(1)关键字k在结点x中,且x是叶结点:
直接删除x中的k。
(2)关键字k在结点x中,且x是内部结点:
a)x->c[i]至少包含t个关键字:
在x中用k的直接前驱k’代替k,递归调用BTreeInsertNonempty(x->c[i],k’)。
b)x->c[i+1]至少包含t个关键字:
在x中用k的直接后继k’代替k,递归调用BTreeInsertNonempty(x->c[i+1],k’)。
c)x->c[i]和x->c[i+1]都只包含t-1个关键字:
调用BTreeMergeChild(x,i),递归调用BTreeDeleteNonempty(x->c[i],k)。
(3)关键字k不在结点x中:
a)x->c[i]只包含t-1个关键字,且x的相邻兄弟至少包含t个关键字:
x向x的相邻兄弟借一个关键字,递归调用BTreeDeleteNonempty(x->c[i],k)。
b)x->c[i]只包含t-1个关键字,且x的相邻兄弟都只包含t个关键字:
合并x和x的相邻兄弟,递归调用BTreeDeleteNonempty(x->c[i-1],k)(左兄弟)或BTreeDeleteNonempty(x->c[i],k)(右兄弟)
c)x->c[i]至少包含t个关键字:
直接递归调用BTreeDeleteNonempty(x->c[i],k)。

#include<iostream>
#include<string>
using namespace std;

const int t=2;

struct node
{
    int n;
    char key[2*t];   //key[0]保留,只使用key[1..2*t-1]
    bool leaf;
    node *c[2*t+1];   //c[0]保留,只使用c[1..2*t]
    node(int a,bool b):n(a),leaf(b){}
};

void BTreeCreate(node *&root)
{
    root=new node(0,true);
}

//x是一个非满结点,x->c[i]是一个满结点
void BTreeSplitChild(node *x,int i)
{
    node *y=x->c[i];
    node *z=new node(t-1,y->leaf);
    for(int j=1;j<=t-1;++j)z->key[j]=y->key[t+j];
    if(!y->leaf)
    {
        for(int j=1;j<=t;++j)z->c[j]=y->c[t+j];
    }
    y->n=t-1;
    for(int j=x->n;j>=i;--j)x->key[j+1]=x->key[j];
    x->key[i]=y->key[t];
    for(int j=x->n+1;j>=i+1;--j)x->c[j+1]=x->c[j];
    x->c[i+1]=z;
    ++x->n;
}

//x是一个非满结点
void BTreeInsertNonfull(node *x,char k)
{
    int i=x->n;
    if(x->leaf)   //x是叶结点
    {
        while(i>=1&&k<x->key[i])
        {
            x->key[i+1]=x->key[i];
            --i;
        }
        x->key[i+1]=k;
        ++x->n;
    }
    else   //x不是叶结点
    {
        while(i>=1&&k<x->key[i])--i;
        ++i;
        if(x->c[i]->n==2*t-1)   //x->c[i]是一个满结点 
        {
            BTreeSplitChild(x,i);
            if(k>x->key[i])++i;
        }
        BTreeInsertNonfull(x->c[i],k);
    }
}

void BTreeInsert(node *&root,char k)
{
    if(root->n==2*t-1)   //根节点是一个满结点
    {
        node *tmp=new node(0,false);
        tmp->c[1]=root;
        root=tmp;
        BTreeSplitChild(root,1);
    }
    BTreeInsertNonfull(root,k);
}

//x至少包含t个关键字,x->c[i]和x->c[i+1]都只包含t-1个关键字
void BTreeMergeChild(node *x,int i)
{
    node *y=x->c[i];
    node *z=x->c[i+1];
    y->key[y->n+1]=x->key[i];
    for(int j=1;j<=t-1;++j)y->key[y->n+1+j]=z->key[j];
    if(!z->leaf)
    {
        for(int j=1;j<=t;++j)y->c[y->n+1+j]=z->c[j];
    }
    y->n=2*t-1;
    for(int j=i+1;j<=x->n;++j)x->key[j-1]=x->key[j];
    for(int j=i+2;j<=x->n+1;++j)x->c[j-1]=x->c[j];
    --x->n;
    delete z;
}

//x至少包含t个关键字
void BTreeDeleteNonempty(node *x,char k)
{
    int i=1;
    while(k>x->key[i])++i;
    if(k==x->key[i])   //关键字k在结点x中
    {
        if(x->leaf)   //x是叶结点
        {
            for(int j=i+1;j<=x->n;++j)x->key[j-1]=x->key[j];
            --x->n;
        }
        else   //x是内部结点
        {
            if(x->c[i]->n>=t)   //x->c[i]至少包含t个关键字
            {
                //直接前驱
                node *p=x->c[i];
                while(!p->leaf)p=p->c[p->n+1];
                x->key[i]=p->key[p->n];
                BTreeDeleteNonempty(x->c[i],p->key[p->n]);
            }
            else if(x->c[i+1]->n>=t)   //x->c[i+1]至少包含t个关键字
            {
                //直接后继
                node *p=x->c[i+1];
                while(!p->leaf)p=p->c[1];
                x->key[i]=p->key[1];
                BTreeDeleteNonempty(x->c[i+1],p->key[1]);
            }
            else   //x->c[i]和x->c[i+1]都只包含t-1个关键字
            {
                BTreeMergeChild(x,i);
                BTreeDeleteNonempty(x->c[i],k);
            }
        }
    }
    else   //关键字k不在结点x中
    {
        if(x->c[i]->n==t-1)   //x->c[i]只包含t-1个关键字
        {
            if(i-1>=1&&x->c[i-1]->n>=t)   //相邻左兄弟至少包含t个关键字
            {
                //x中的关键字降至x->c[i]
                for(int j=x->c[i]->n;j>=1;--j)x->c[i]->key[j+1]=x->c[i]->key[j];
                x->c[i]->key[1]=x->key[i-1];
                //x->c[i-1]中的关键字升至x
                x->key[i-1]=x->c[i-1]->key[x->c[i-1]->n];
                if(!x->c[i-1]->leaf)
                {
                    for(int j=x->c[i]->n+1;j>=1;++j)x->c[i]->c[j+1]=x->c[i]->c[j];
                    x->c[i]->c[1]=x->c[i-1]->c[x->c[i-1]->n+1];
                }
                ++x->c[i]->n;
                --x->c[i-1]->n;
                BTreeDeleteNonempty(x->c[i],k);
            }
            else if(i+1<=x->n+1&&x->c[i+1]->n>=t)   //相邻右兄弟至少包含t个关键字
            {
                //x中的关键字降至x->c[i]
                x->c[i]->key[x->c[i]->n+1]=x->key[i];
                //x->c[i+1]中的关键字升至x
                x->key[i]=x->c[i+1]->key[1];
                for(int j=2;j<=x->c[i+1]->n;++j)x->c[i+1]->key[j-1]=x->c[i+1]->key[j];
                if(!x->c[i+1]->leaf)
                {
                    x->c[i]->c[x->c[i]->n+2]=x->c[i+1]->c[1];
                    for(int j=2;j<=x->c[i+1]->n+1;++j)x->c[i+1]->c[j-1]=x->c[i+1]->c[j];
                }
                ++x->c[i]->n;
                --x->c[i+1]->n;
                BTreeDeleteNonempty(x->c[i],k);
            }
            else   //相邻左右兄弟都只包含t-1个关键字      
            {
                if(i-1>=1)   //相邻左兄弟
                {
                    BTreeMergeChild(x,i-1);
                    BTreeDeleteNonempty(x->c[i-1],k);
                }
                else   //相邻右兄弟
                {
                    BTreeMergeChild(x,i);
                    BTreeDeleteNonempty(x->c[i],k);
                }
            }
        }
        else BTreeDeleteNonempty(x->c[i],k);   //x->c[i]至少包含t个关键字
    }
}

void BTreeDelete(node *&root,char k)
{
    if(root->n==1&&!root->leaf&&root->c[1]->n==t-1&&root->c[2]->n==t-1)   //case 2c或case 3b
    {
        BTreeMergeChild(root,1);
        node *tmp=root;
        root=root->c[1];
        delete tmp;
    }
    BTreeDeleteNonempty(root,k);
}

//             KQ
//       /     |      \ 
//      BF     M      TW
//   /  |  \  / \   / | \
//   A CDE H  L NP RS V XYZ

int main()
{
    node *root;
    BTreeCreate(root);
    string s="FSQKCLHTVWMRNPABXYDZE";
    for(int i=0;i<s.size();++i)BTreeInsert(root,s[i]);
    for(int i=0;i<s.size();++i)BTreeDelete(root,s[i]);
    return 0;
}

从B树、B+树、B*树谈到R 树:
http://blog.csdn.net/v_july_v/article/details/6530142

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值