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;
}