`

[转]B+树的结构和实现代码

 
阅读更多
<iframe align="center" marginwidth="0" marginheight="0" src="http://www.zealware.com/csdnblog336280.html" frameborder="0" width="336" scrolling="no" height="280"></iframe>

B+树实现代码

来源:http://supercyber.139.com/article/253784.html

这个结构一般用于数据库的索引,综合效率非常高,像 Berkerly DB , sqlite , mysql 数据库都使用了这个算法处理索引。
如果想自己做个小型数据库,可能参考一下这个算法的实现,可能会对你有所帮助。

其中的注册很详细,不用再多说了。

/*btrees.h*/
/*
*平衡多路树的一种重要方案。
*在1970年由R.Bayer和E.McCreight发明。
*/
#defineM1
/*B树的阶,即非根节点中键的最小数目。
*有些人把阶定义为非根节点中子树的最大数目。
*/
typedef
inttypekey;
typedef
structbtnode{/*B-Tree节点*/
intd;/*节点中键的数目*/
typekeyk[
2*M];/**/
char*v[2*M];/**/
structbtnode*p[2*M+1];/*指向子树的指针*/
}node,
*btree;
/*
*每个键的左子树中的所有的键都小于这个键,
*每个键的右子树中的所有的键都大于等于这个键。
*叶子节点中的每个键都没有子树。
*/

/*当M等于1时也称为2-3树
*+----+----+
*|k0|k1|
*+-+----+----+---
*|p0|p1|p2|
*+----+----+----+
*/
externintbtree_disp;/*查找时找到的键在节点中的位置*/
externchar*InsValue;/*与要插的键相对应的值*/

externbtreesearch(typekey,btree);
externbtreeinsert(typekey,btree);
externbtreedelete(typekey,btree);
externintheight(btree);
externintcount(btree);
externdoublepayload(btree);
externbtreedeltree(btree);
/*endofbtrees.h*/

/*******************************************************/

/*******************************************************/

/*btrees.c*/
#include
#include
#include
"btrees.h"

btreesearch(typekey,btree);
btreeinsert(typekey,btree);
btreedelete(typekey,btree);
intheight(btree);
intcount(btree);
doublepayload(btree);
btreedeltree(btree);

staticvoidInternalInsert(typekey,btree);
staticvoidInsInNode(btree,int);
staticvoidSplitNode(btree,int);
staticbtreeNewRoot(btree);

staticvoidInternalDelete(typekey,btree);
staticvoidJoinNode(btree,int);
staticvoidMoveLeftNode(btreet,int);
staticvoidMoveRightNode(btreet,int);
staticvoidDelFromNode(btreet,int);
staticbtreeFreeRoot(btree);

staticbtreedelall(btree);
staticvoidError(int,typekey);

intbtree_disp;/*查找时找到的键在节点中的位置*/
char*InsValue=NULL;/*与要插的键相对应的值*/
staticintflag;/*节点增减标志*/
staticintbtree_level=0;/*多路树的高度*/
staticintbtree_count=0;/*多路树的键总数*/
staticintnode_sum=0;/*多路树的节点总数*/
staticintlevel;/*当前访问的节点所处的高度*/
staticbtreeNewTree;/*在节点分割的时候指向新建的节点*/
statictypekeyInsKey;/*要插入的键*/

btreesearch(typekeykey,btreet)
{
inti,j,m;
level
=btree_level-1;
while(level>=0){
for(i=0,j=t->d-1;it->k[m])?(i=m+1):(j=m));
if(key==t->k){
btree_disp
=i;
returnt;
}
if(key>t->k)/*i==t->d-1时有可能出现*/
i
++;
t
=t->p;
level
--;
}
returnNULL;
}

btreeinsert(typekeykey,btreet)
{
level
=btree_level;
InternalInsert(key,t);
if(flag==1)/*根节点满之后,它被分割成两个半满节点*/
t
=NewRoot(t);/*树的高度增加*/
returnt;
}

voidInternalInsert(typekeykey,btreet)
{
inti,j,m;

level
--;
if(level0){/*到达了树的底部:指出要做的插入*/
NewTree
=NULL;/*这个键没有对应的子树*/
InsKey
=key;/*导致底层的叶子节点增加键值+空子树对*/
btree_count
++;
flag
=1;/*指示上层节点把返回的键插入其中*/
return;
}
for(i=0,j=t->d-1;it->k[m])?(i=m+1):(j=m));
if(key==t->k){
Error(
1,key);/*键已经在树中*/
flag
=0;
return;
}
if(key>t->k)/*i==t->d-1时有可能出现*/
i
++;
InternalInsert(key,t
->p);

if(flag==0)
return;
/*有新键要插入到当前节点中*/
if(t->d2*M){/*当前节点未满*/
InsInNode(t,i);
/*把键值+子树对插入当前节点中*/
flag
=0;/*指示上层节点没有需要插入的键值+子树,插入过程结束*/
}
else/*当前节点已满,则分割这个页面并把键值+子树对插入当前节点中*/
SplitNode(t,i);
/*继续指示上层节点把返回的键值+子树插入其中*/
}

/*
*把一个键和对应的右子树插入一个节点中
*/
voidInsInNode(btreet,intd)
{
inti;
/*把所有大于要插入的键值的键和对应的右子树右移*/
for(i=t->d;i>d;i--){
t
->k=t->k[i-1];
t
->v=t->v[i-1];
t
->p[i+1]=t->p;
}
/*插入键和右子树*/
t
->k=InsKey;
t
->p[i+1]=NewTree;
t
->v=InsValue;
t
->d++;
}
/*
*前件是要插入一个键和对应的右子树,并且本节点已经满
*导致分割这个节点,插入键和对应的右子树,
*并向上层返回一个要插入键和对应的右子树
*/
voidSplitNode(btreet,intd)
{
inti,j;
btreetemp;
typekeytemp_k;
char*temp_v;
/*建立新节点*/
temp
=(btree)malloc(sizeof(node));
/*
*+---+--------+-----+-----+--------+-----+
*|0|......|M|M+1|......|2*M-1|
*+---+--------+-----+-----+--------+-----+
*|||
*/
if(d>M){/*要插入当前节点的右半部分*/
/*把从2*M-1到M+1的M-1个键值+子树对转移到新节点中,
*并且为要插入的键值+子树空出位置
*/
for(i=2*M-1,j=M-1;i>=d;i--,j--){
temp
->k[j]=t->k;
temp
->v[j]=t->v;
temp
->p[j+1]=t->p[i+1];
}
for(i=d-1,j=d-M-2;j>=0;i--,j--){
temp
->k[j]=t->k;
temp
->v[j]=t->v;
temp
->p[j+1]=t->p[i+1];
}
/*把节点的最右子树转移成新节点的最左子树*/
temp
->p[0]=t->p[M+1];
/*在新节点中插入键和右子树*/
temp
->k[d-M-1]=InsKey;
temp
->p[d-M]=NewTree;
temp
->v[d-M-1]=InsValue;
/*设置要插入上层节点的键和值*/
InsKey
=t->k[M];
InsValue
=t->v[M];

}
else{/*d*/
/*把从2*M-1到M的M个键值+子树对转移到新节点中*/
for(i=2*M-1,j=M-1;j>=0;i--,j--){
temp
->k[j]=t->k;
temp
->v[j]=t->v;
temp
->p[j+1]=t->p[i+1];
}
if(d==M)/*要插入当前节点的正中间*/
/*把要插入的子树作为新节点的最左子树*/
temp
->p[0]=NewTree;
/*直接把要插入的键和值返回给上层节点*/
else{/*(d/*把节点当前的最右子树转移成新节点的最左子树*/
temp
->p[0]=t->p[M];
/*保存要插入上层节点的键和值*/
temp_k
=t->k[M-1];
temp_v
=t->v[M-1];
/*把所有大于要插入的键值的键和对应的右子树右移*/
for(i=M-1;i>d;i--){
t
->k=t->k[i-1];
t
->v=t->v[i-1];
t
->p[i+1]=t->p;
}
/*在节点中插入键和右子树*/
t
->k[d]=InsKey;
t
->p[d+1]=NewTree;
t
->v[d]=InsValue;
/*设置要插入上层节点的键和值*/
InsKey
=temp_k;
InsValue
=temp_v;
}
}
t
->d=M;
temp
->d=M;
NewTree
=temp;
node_sum
++;
}

btreedelete(typekeykey,btreet)
{
level
=btree_level;
InternalDelete(key,t);
if(t->d==0)
/*根节点的子节点合并导致根节点键的数目随之减少,
*当根节点中没有键的时候,只有它的最左子树可能非空
*/
t
=FreeRoot(t);
returnt;
}

voidInternalDelete(typekeykey,btreet)
{
inti,j,m;
btreel,r;
intlvl;

level
--;
if(level0){
Error(
0,key);/*在整个树中未找到要删除的键*/
flag
=0;
return;
}
for(i=0,j=t->d-1;it->k[m])?(i=m+1):(j=m));
if(key==t->k){/*找到要删除的键*/
if(t->v!=NULL)
free(t
->v);/*释放这个节点包含的值*/
if(level==0){/*有子树为空则这个键位于叶子节点*/
DelFromNode(t,i);
btree_count
--;
flag
=1;
/*指示上层节点本子树的键数量减少*/
return;
}
else{/*这个键位于非叶节点*/
lvl
=level-1;
/*找到前驱节点*/
r
=t->p;
while(lvl>0){
r
=r->p[r->d];
lvl
--;
}
t
->k=r->k[r->d-1];
t
->v=r->v[r->d-1];
r
->v[r->d-1]=NULL;
key
=r->k[r->d-1];
}
}
elseif(key>t->k)/*i==t->d-1时有可能出现*/
i
++;
InternalDelete(key,t
->p);
/*调整平衡*/
if(flag==0)
return;
if(t->p->dM){
if(i==t->d)/*在最右子树中发生了删除*/
i
--;/*调整最右键的左右子树平衡*/
l
=t->p;
r
=t->p[i+1];
if(r->d>M)
MoveLeftNode(t,i);
elseif(l->d>M)
MoveRightNode(t,i);
else{
JoinNode(t,i);
/*继续指示上层节点本子树的键数量减少*/
return;
}
flag
=0;
/*指示上层节点本子树的键数量没有减少,删除过程结束*/
}
}

/*
*合并一个节点的某个键对应的两个子树
*/
voidJoinNode(btreet,intd)
{
btreel,r;
inti,j;
l
=t->p[d];
r
=t->p[d+1];

/*把这个键下移到它的左子树*/
l
->k[l->d]=t->k[d];
l
->v[l->d]=t->v[d];
/*把右子树中的所有键值和子树转移到左子树*/
for(j=r->d-1,i=l->d+r->d;j>=0;j--,i--){
l
->k=r->k[j];
l
->v=r->v[j];
l
->p=r->p[j];
}
l
->p[l->d+r->d+1]=r->p[r->d];
l
->d+=r->d+1;
/*释放右子树的节点*/
free(r);
/*把这个键右边的键和对应的右子树左移*/
for(i=d;it->d-1;i++){
t
->k=t->k[i+1];
t
->v=t->v[i+1];
t
->p[i+1]=t->p[i+2];
}
t
->d--;
node_sum
--;
}
/*
*从一个键的右子树向左子树转移一些键,使两个子树平衡
*/
voidMoveLeftNode(btreet,intd)
{
btreel,r;
intm;/*应转移的键的数目*/
inti,j;
l
=t->p[d];
r
=t->p[d+1];
m
=(r->d-l->d)/2;

/*把这个键下移到它的左子树*/
l
->k[l->d]=t->k[d];
l
->v[l->d]=t->v[d];
/*把右子树的最左子树转移成左子树的最右子树
*从右子树向左子树移动m-1个键+子树对
*/
for(j=m-2,i=l->d+m-1;j>=0;j--,i--){
l
->k=r->k[j];
l
->v=r->v[j];
l
->p=r->p[j];
}
l
->p[l->d+m]=r->p[m-1];
/*把右子树的最左键提升到这个键的位置上*/
t
->k[d]=r->k[m-1];
t
->v[d]=r->v[m-1];
/*把右子树中的所有键值和子树左移m个位置*/
r
->p[0]=r->p[m];
for(i=0;id-m;i++){
r
->k=r->k[i+m];
r
->v=r->v[i+m];
r
->p=r->p[i+m];
}
r
->p[r->d-m]=r->p[r->d];
l
->d+=m;
r
->d-=m;
}
/*
*从一个键的左子树向右子树转移一些键,使两个子树平衡
*/
voidMoveRightNode(btreet,intd)
{
btreel,r;
intm;/*应转移的键的数目*/
inti,j;
l
=t->p[d];
r
=t->p[d+1];

m
=(l->d-r->d)/2;
/*把右子树中的所有键值和子树右移m个位置*/
r
->p[r->d+m]=r->p[r->d];
for(i=r->d-1;i>=0;i--){
r
->k[i+m]=r->k;
r
->v[i+m]=r->v;
r
->p[i+m]=r->p;
}
/*把这个键下移到它的右子树*/
r
->k[m-1]=t->k[d];
r
->v[m-1]=t->v[d];
/*把左子树的最右子树转移成右子树的最左子树*/
r
->p[m-1]=l->p[l->d];
/*从左子树向右子树移动m-1个键+子树对*/
for(i=l->d-1,j=m-2;j>=0;j--,i--){
r
->k[j]=l->k;
r
->v[j]=l->v;
r
->p[j]=l->p;
}
/*把左子树的最右键提升到这个键的位置上*/
t
->k[d]=l->k;
t
->v[d]=l->v;
l
->d-=m;
r
->d+=m;
}
/*
*把一个键和对应的右子树从一个节点中删除
*/
voidDelFromNode(btreet,intd)
{
inti;
/*把所有大于要删除的键值的键左移*/
for(i=d;it->d-1;i++){
t
->k=t->k[i+1];
t
->v=t->v[i+1];
}
t
->d--;
}
/*
*建立有两个子树和一个键的根节点
*/
btreeNewRoot(btreet)
{
btreetemp;
temp
=(btree)malloc(sizeof(node));
temp
->d=1;
temp
->p[0]=t;
temp
->p[1]=NewTree;
temp
->k[0]=InsKey;
temp
->v[0]=InsValue;
btree_level
++;
node_sum
++;
return(temp);
}
/*
*释放根节点,并返回它的最左子树
*/
btreeFreeRoot(btreet)
{
btreetemp;
temp
=t->p[0];
free(t);
btree_level
--;
node_sum
--;
returntemp;
}

voidError(intf,typekeykey)
{
if(f)
printf(
"Btreeserror:Insert%d! ",key);
else
printf(
"Btreeserror:delete%d! ",key);
}

intheight(btreet)
{
returnbtree_level;
}

intcount(btreet)
{
returnbtree_count;
}
doublepayload(btreet)
{
if(node_sum==0)
return1;
return(double)btree_count/(node_sum*(2*M));
}
btreedeltree(btreet)
{
level
=btree_level;
btree_level
=0;
returndelall(t);

}
btreedelall(btreet)
{
inti;
level
--;
if(level>=0){
for(i=0;it->d;i++)
if(t->v!=NULL)
free(t
->v);
if(level>0)
for(i=0;it->d;i++)
t
->p=delall(t->p);
free(t);
}
returnNULL;
}

/*endofbtrees.c*/


B+树的组织结构

来源:http://www.blogjava.net/titan/articles/30387.html

1、B+树索引的总体结构
①B+树索引是一个多级索引,但是其结构不同于多级顺序索引;
②B+树索引采用平衡树结构,即每个叶结点到根的路径长度都相同;
③每个非叶结点有到n个子女,n对特定的树是固定的;
④B+树的所有结点结构都相同,它最多包含n-1个搜索码值K1、K2、…、Kn-1,以及n个指针P1、P2、…、Pn,每个结点中的搜索码值按次序存放,即如果i<j class="part">图8-3-1所示。<br></j>

图8-3-1:B+树的结点结构
2、B+树索引的叶结点
①指针Pi(i=1,2,…,n-1)指向具有搜索码值Ki的一个文件记录或一个指针(存储)桶,桶中的每个指针指向具有搜索码值Ki的一个文件记录。指针桶只在文件不按搜索码顺序物理存储时才使用。指针Pn具有特殊的作用;
②每个叶结点最多可有n-1个搜索码值,最少也要有个搜索码值。各个叶结点中搜索码值的范围互不相交。要使B+树索引成为稠密索引,数据文件中的各搜索码值都必须出现在某个叶结点中且只能出现一次;
③由于各叶结点按照所含的搜索码值有一个线性顺序,所以就可以利用各个叶结点的指针Pn将叶结点按搜索码顺序链接在一起。这种排序能够高效地对文件进行顺序处理,而B+树索引的其他结构能够高效地对文件进行随机处理,如图8-3-2所示。
图8-3-2:B+树索引的叶结点结构示例
3、B+树索引的非叶结点
①B+树索引的非叶结点形成叶结点上的一个多级(稀疏)索引;
②非叶结点的结构和叶结点的结构相同,即含有能够存储n-1个搜索码值和n个指针的存储单元的数据结构。只不过非叶结点中的所有指针都指向树中的结点;
③如果一个非叶结点有m个指针,则≤m≤n。若m<n class="part">图8-3-3所示;<br></n>
图8-3-3:B+树索引的非叶结点结构
④在一个含有m个指针的非叶结点中,指针Pi(i=2,…,m-1)指向一棵子树,该子树的所有结点的搜索码值大于等于Ki-1而小于Ki。指针Pm指向子树中所含搜索码值大于等于Km-1的那一部分,而指针P1指向子树中所含搜索码值小于K1的那一部分,如图8-3-4所示。
图8-3-4:B+树索引的非叶结点中指针Pi的指向
4、B+树索引的根结点
①根结点的结构也与叶结点相同;
②根结点包含的指针数可以小于。但是,除非整棵树只有一个结点,否则根结点必须至少包含两个指针。图8-3-5给出一个B+树结构的示意图。
图8-3-5:account关系的B+树索引结构

其他:

B+树其他信息:

http://www.google.cn/search?complete=1&hl=zh-CN&q=B%2B%E6%A0%91&meta=

http://www.baidu.com/s?wd=B%2B%CA%F7&cl=3




分享到:
评论

相关推荐

    B+树的c语言代码实现

    与B树相比,B+树的所有叶子节点都位于同一层,且叶子节点之间通过指针相互连接,这使得B+树非常适合范围查询和顺序访问。 #### 三、代码结构分析 1. **文件头注释**: - 作者:bysvking - 时间:2012年5月 - ...

    B+树C++代码实现

    1. **B+树结构** - **根节点**:B+树的根节点可以是叶节点,也可以是非叶节点,但通常至少包含两个子节点。 - **分支节点(非叶节点)**:非叶节点不存储实际数据,仅包含指向子节点的指针,以及每个子节点对应的...

    b+树实现原代码

    在提供的“b+树实现原代码.doc”文档中,我们可以预期看到以下关键部分: 1. **节点结构定义**:包括非叶子节点和叶子节点的定义,通常包含键值数组、子节点指针数组以及可能的数据存储区域。 2. **插入函数**:...

    B-树 B+树 源代码 C++ 数据结构

    本项目提供的源代码是C++实现的B-树和B+树,有助于学习者深入理解这两种数据结构的内部机制。 首先,B-树(Balanced Tree)是一种自平衡的多路搜索树,它的每个节点可以有多个子节点,通常为2到32个。B-树的主要...

    B+树,源代码,B+树,源代码

    若在非叶子节点,需要找到对应的叶子节点,再进行删除处理,可能涉及到合并节点和调整树结构。 5. **遍历操作**:由于叶子节点之间有指针,可以方便地实现从第一个叶子节点到最后一个叶子节点的遍历。 在压缩包中,...

    【源码】C#的B+树实现和原理解析

    在IT领域,数据结构是构建高效算法的基础,而B+树作为一种自平衡的搜索树,...同时,对B+树的理解也将有助于你更好地理解和使用数据库管理系统,例如MySQL、Oracle等,它们内部的索引机制很大程度上依赖于B树或B+树。

    JAVA B+树的实现

    本文将深入探讨如何在Java环境中实现B+树,包括其基本概念、特性以及如何用Java代码来构建和操作B+树。 首先,B+树是一种自平衡的多路搜索树,它的主要特点是所有叶子节点都在同一层,并且每个非叶子节点只存储键值...

    B-树和B+树的源代码

    C++实现B-树和B+树的代码会包括以下关键部分: - **节点定义**:定义B-树或B+树的节点结构,包括关键字、子节点指针、可能的数据存储等。 - **插入操作**:根据树的性质,找到合适的插入位置,可能涉及节点的分裂。 ...

    B+树的源代码

    学习B+树的源代码可以帮助我们深入理解其内部工作机制,包括节点的分裂、合并以及查找、插入和删除操作的具体实现。这对于优化数据库索引设计和提升系统性能有着重要的理论与实践意义。通过分析源代码,我们可以更好...

    b+/-树的实现源代码

    B+树和B-树是计算机科学中用于数据库和文件系统等数据存储的重要数据结构,它们主要用于高效地管理大量数据,特别是当数据需要在磁盘等慢速存储介质上进行操作时。这两种树都是自平衡的,能保持数据的有序性,并且在...

    VC++ B+树的实现

    测试代码可以创建不同的场景,验证插入、删除和查找操作的正确性,确保B+树的实现符合预期。 通过以上步骤,我们可以在VC++环境中实现一个功能完备的B+树数据结构,为数据的高效存储和检索提供基础。这不仅有助于...

    B.rar_B+树_B+树 C++实现_B树_visual c

    - **BPlusTree.cpp**:可能包含了B+树的实现代码,包括节点类定义、插入、删除和查找函数等。 - **DemoB.cpp**:可能是演示如何使用B+树的示例代码,展示了如何创建、插入和查询数据。 - **BPlusTree.h**:头文件,...

    B+树的创建(java源码)

    在计算机科学领域,数据结构是基础且至关重要的部分,B+树作为一种自平衡的查找树,广泛应用于数据库和文件系统中。本节将详细讲解如何使用Java实现B+树,包括其基本概念、节点结构、树的构建、插入操作以及遍历方法...

    B+树作为数据库的索引

    提供的压缩包文件" B+树 "可能包含了B+树的C语言实现,用户可以下载后进行编译运行,以理解和实践B+树的构建和查询过程。这样的实践有助于加深对B+树原理的理解,以及如何将其应用于实际数据库索引中。 总结来说,B...

    B+树索引源代码例程

    通过学习和理解这个B+树源代码例程,开发者不仅可以掌握B+树的工作原理,还能学会如何在实际项目中应用这种数据结构,提升数据库或文件系统的查询效率。同时,源代码分析对于理解数据结构的实现细节和优化策略也...

    B+树代码实现

    相较于二叉搜索树、B树等其他树形结构,B+树更加适合于基于磁盘存储的大规模数据处理。 #### 二、代码实现解析 根据提供的部分代码,我们可以看到这是一个B+树的C++实现案例,主要涉及到以下几个方面: 1. **定义...

    C++ 数据结构 算法B+树实现

    此外,为了调试和理解代码,可以实现打印功能,将B+树的结构可视化。 总的来说,掌握B+树的实现对于理解和优化数据库查询性能至关重要。在C++中实现B+树涉及到对数据结构的理解、指针操作以及内存管理,这些技能都...

    b_plus_tree.rar_b+tree_b+tree磁盘_b+树 文件_plus_磁盘实现B+树

    3. **BTree.cpp**:这是B+树的实现代码文件,其中包含了B+树的数据结构定义、插入、删除、搜索等核心操作的函数。 4. **project4Dlg.cpp**:可能包含与用户交互的对话框相关的代码,例如用于显示B+树的结构或接收...

    b+b-树c语言版

    4. **删除**:删除关键字时要考虑节点是否为空,以及删除后如何调整树结构以保持平衡。如果删除导致节点元素不足,可能需要合并节点或移动元素。 **C语言实现** C语言是一种底层编程语言,适合实现数据结构的底层...

    变长文件存取类库 B+树实现

    本文将详细解析"变长文件存取类库 B+树实现"的相关知识点,以及如何通过模板对B+树进行抽象以提高代码的可复用性和灵活性。 首先,理解B+树(B Plus Tree)的基本概念至关重要。B+树是一种自平衡的多路搜索树,具有...

Global site tag (gtag.js) - Google Analytics