B-树是一种平衡的多路查找树,它有较高的查找的效率,在文件系统中很有用.
一、B-树的定义
一棵"m 阶的B树"或为空树,或为具有以下特性的 m 叉查找树:
(1)树中每个结点至多有 m 棵子树;
(2)除根以外的所有非叶结点至少有 [m/2 ]棵子树,根结点若是非叶结点,则至少有两棵子树;
(3)所有的非叶结点中含有如下信息:
(n,A0,(K1,D1),A1,(K2,D2),……,An-1,(Kn,Dn),An)
其中:(Ki,Di)(i=1,…,n)为索引项,且 Ki<Ki+1(i=1,…,n-1);Ai(i=0,…,n) 为指向子树根结点的指针,且 Ai-1 所指子树中所有索引项的关键码小于 Ki(i=1,…,n),An 所指子树中索引项的关键码大于 Kn,n(m/2-1≤n≤m-1) 为结点中索引项的个数;
(4)所有叶结点都在同一层上,且不含任何信息。
下图为一棵4阶树:
二,B-树的实现
下面为c代码,参照了<<数据结构>>(严蔚敏)一书中的算法:
#include
<
stdio.h
>
#include < malloc.h >
#define FALSE 0
#define TRUE 1
#define m 3
typedef int KeyType;
typedef struct BTNode
... {
int keynum;
struct BTNode *parent;
KeyType key[m+1];
struct BTNode *ptr[m+1];
} BTNode, * BTree;
typedef struct
... {
BTNode *pt;
int i;
int tag;
} Result;
// 设结点中的指针向量为空
void SetNull(BTree & p)
... {
int i=0;
while(i<=p->keynum)
...{
p->ptr[i]=NULL;
i++;
}
}
// 在结点中查找关键字
int SearchNode(BTree p,KeyType k)
... {
int i=1;
while(i<=p->keynum)
...{
if(k<p->key[i])
return i-1;
i++;
}
return i-1;
}
// 在B树中查找关键字k
Result SearchBTree(BTree t,KeyType k)
... {
BTree p=t,q=NULL;
bool found=FALSE;
int i=0;
Result result;
while(p&&!found)
...{
i=SearchNode(p,k);
if(i>0&&p->key[i]==k)
found=TRUE;
else
...{
q=p;
p=p->ptr[i];
}
}
if(found)
...{
result.pt=p;
result.i=i;
result.tag=1;
}
else
...{
result.pt=q;
result.i=i;
result.tag=0;
}
return result;
}
// 在结点中插入新的关键字k和指针pt
void InsertInNode(BTree & q, int i,KeyType k,BTree pt)
... {
int j;
for(j=q->keynum;j>i;j--)
q->key[j+1]=q->key[j];
q->key[j+1]=k;
for(j=q->keynum;j>i;j--)
q->ptr[j+1]=q->ptr[j];
q->ptr[j+1]=pt;
if(pt)
...{
pt->parent=q;
}
q->keynum++;
}
// 分裂结点p
void Split(BTree p,BTree & q)
... {
int s=m%2==0?m/2-1:m/2,i,j=0;
p->keynum=s;
q=(BTree)malloc(sizeof(BTNode));
SetNull(q);
for(i=s+2;i<=m;i++)
...{
q->ptr[j]=p->ptr[i-1];
q->key[++j]=p->key[i];
}
q->ptr[j]=p->ptr[i-1];
q->keynum=j;
}
// 在q结点第i个位置插入关键字
void InsertBTree(BTree & t,KeyType k,BTree q, int i)
... {
BTree ap=NULL,root;
bool finish=FALSE;
int s;
KeyType x=k;
while(q&&!finish)
...{
InsertInNode(q,i,x,ap);
if(q->keynum<m)
finish=TRUE;
else
...{
s=m%2==0?m/2:m/2+1;
Split(q,ap);
x=q->key[s];
q=q->parent;
if(q)
i=SearchNode(q,x);
}
}
if(!finish)
...{
root=(BTree)malloc(sizeof(BTNode));
SetNull(root);
root->key[1]=x;
root->ptr[0]=t;
root->ptr[1]=ap;
root->keynum=1;
root->parent=NULL;
if(t)
t->parent=root;
if(ap)
ap->parent=root;
t=root;
}
}
// 在B树中插入一个关键字
void InsertNode(BTree & t,KeyType key)
... {
Result result;
result=SearchBTree(t,key);
if(!result.tag)
...{
InsertBTree(t,key,result.pt,result.i);
}
}
// 中序遍历B树
void PrintBTree(BTree t)
... {
if(t)
...{
int i=1;
while(i<=t->keynum)
...{
PrintBTree(t->ptr[i-1]);
printf("%d,",t->key[i]);
i++;
}
PrintBTree(t->ptr[i-1]);
}
}
int main( int argc, char * argv[])
... {
BTree root=NULL;
int array[]=...{9,5,8,3,2,4,7};
for(int i=0;i<7;i++)
InsertNode(root,array[i]); //插入结点
printf("printing ... ");
PrintBTree(root);//遍历结点
}
#include < malloc.h >
#define FALSE 0
#define TRUE 1
#define m 3
typedef int KeyType;
typedef struct BTNode
... {
int keynum;
struct BTNode *parent;
KeyType key[m+1];
struct BTNode *ptr[m+1];
} BTNode, * BTree;
typedef struct
... {
BTNode *pt;
int i;
int tag;
} Result;
// 设结点中的指针向量为空
void SetNull(BTree & p)
... {
int i=0;
while(i<=p->keynum)
...{
p->ptr[i]=NULL;
i++;
}
}
// 在结点中查找关键字
int SearchNode(BTree p,KeyType k)
... {
int i=1;
while(i<=p->keynum)
...{
if(k<p->key[i])
return i-1;
i++;
}
return i-1;
}
// 在B树中查找关键字k
Result SearchBTree(BTree t,KeyType k)
... {
BTree p=t,q=NULL;
bool found=FALSE;
int i=0;
Result result;
while(p&&!found)
...{
i=SearchNode(p,k);
if(i>0&&p->key[i]==k)
found=TRUE;
else
...{
q=p;
p=p->ptr[i];
}
}
if(found)
...{
result.pt=p;
result.i=i;
result.tag=1;
}
else
...{
result.pt=q;
result.i=i;
result.tag=0;
}
return result;
}
// 在结点中插入新的关键字k和指针pt
void InsertInNode(BTree & q, int i,KeyType k,BTree pt)
... {
int j;
for(j=q->keynum;j>i;j--)
q->key[j+1]=q->key[j];
q->key[j+1]=k;
for(j=q->keynum;j>i;j--)
q->ptr[j+1]=q->ptr[j];
q->ptr[j+1]=pt;
if(pt)
...{
pt->parent=q;
}
q->keynum++;
}
// 分裂结点p
void Split(BTree p,BTree & q)
... {
int s=m%2==0?m/2-1:m/2,i,j=0;
p->keynum=s;
q=(BTree)malloc(sizeof(BTNode));
SetNull(q);
for(i=s+2;i<=m;i++)
...{
q->ptr[j]=p->ptr[i-1];
q->key[++j]=p->key[i];
}
q->ptr[j]=p->ptr[i-1];
q->keynum=j;
}
// 在q结点第i个位置插入关键字
void InsertBTree(BTree & t,KeyType k,BTree q, int i)
... {
BTree ap=NULL,root;
bool finish=FALSE;
int s;
KeyType x=k;
while(q&&!finish)
...{
InsertInNode(q,i,x,ap);
if(q->keynum<m)
finish=TRUE;
else
...{
s=m%2==0?m/2:m/2+1;
Split(q,ap);
x=q->key[s];
q=q->parent;
if(q)
i=SearchNode(q,x);
}
}
if(!finish)
...{
root=(BTree)malloc(sizeof(BTNode));
SetNull(root);
root->key[1]=x;
root->ptr[0]=t;
root->ptr[1]=ap;
root->keynum=1;
root->parent=NULL;
if(t)
t->parent=root;
if(ap)
ap->parent=root;
t=root;
}
}
// 在B树中插入一个关键字
void InsertNode(BTree & t,KeyType key)
... {
Result result;
result=SearchBTree(t,key);
if(!result.tag)
...{
InsertBTree(t,key,result.pt,result.i);
}
}
// 中序遍历B树
void PrintBTree(BTree t)
... {
if(t)
...{
int i=1;
while(i<=t->keynum)
...{
PrintBTree(t->ptr[i-1]);
printf("%d,",t->key[i]);
i++;
}
PrintBTree(t->ptr[i-1]);
}
}
int main( int argc, char * argv[])
... {
BTree root=NULL;
int array[]=...{9,5,8,3,2,4,7};
for(int i=0;i<7;i++)
InsertNode(root,array[i]); //插入结点
printf("printing ... ");
PrintBTree(root);//遍历结点
}
原文:http://blog.csdn.net/arrowcat/archive/2008/04/07/2256454.aspx