算法导论18(B树)

来源:互联网 发布:mac驱动下载 编辑:程序博客网 时间:2024/05/21 12:31

插入
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 XYZint 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
原创粉丝点击