插入
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