B-树

当查找的文件较大,且存放在磁盘等直接存取设备中时,为了减少查找过程中对磁盘的读写次数,提高查找效率,基于直接存取设备的读写操作以"页"为单位的特征。
1972年R.Bayer和E.M.McCreight提出了一种称之为B-树的多路平衡查找树。它适合在磁盘等直接存取设备上组织动态的查找表。

1、定义与特性

B-树是一种平衡的多路查找树,在文件系统中有所应用。主要用作文件的索引。

一棵m阶B-树,或为空树,或为满足下列特性的m叉树:(m≥3)

(1)根结点只有1个,关键字字数的范围[1,m-1],分支数量范围[2,m];

(2)除根以外的非叶结点,关键字字数的范围是[[m/2]-1,m-1],即每个结点包含分支数范围[[m/2],m],其中[m/2]表示取大于m/2的最小整数;

(3)非叶结点是由叶结点分裂而来的,所以叶结点关键字个数也满足[[m/2]-1,m-1];

(4)所有的非终端结点包含信息:(n,P0,K1,P1,K2,P2,……,Kn,Pn),

 其中Ki为关键字,Pi为指向子树根结点的指针,并且Pi-1所指子树中的关键字均小于Ki,而Pi所指的关键字均大于Ki(i=1,2,……,n),n+1表示B-树的阶,n表示关键字个数,即[ceil(m / 2)-1]<= n <= m-1;

(5)所有叶子结点都在同一层,并且指针域为空,具有如下性质:

根据B-树定义,第一层为根有一个结点,至少两个分支,第二层至少2个结点,i≥3时,每一层至少有2乘以([m/2])的i-2次方个结点([m/2]表示取大于m/2的最小整数)。若m阶树中共有N个结点,那么可以推导出N必然满足N≥2*(([m/2])的h-1次方)-1 (h≥1),因此若查找成功,则高度h≤1+log[m/2](N+1)/2,h也是磁盘访问次数(h≥1),保证了查找算法的高效率。

从以上的定义特性可总结出如下结论:对于m阶B-树

1)树中每个结点最多含有m个孩子(m>=2);

2)除根结点和叶子结点外,其它每个结点至少有[ceil(m / 2)]个孩子(其中ceil(x)是一个取上限的函数);

3)若根结点不是叶子结点,则至少有2个孩子(特殊情况:没有孩子的根结点,即根结点为叶子结点,整棵树只有一个根节点);

4)所有叶子结点都出现在同一层,叶子结点不包含任何关键字信息(叶子节点只是没有孩子和指向孩子的指针,这些节点也存在,也有元素)。

5)每个非终端结点中包含有n个关键字信息: (n,P0,K1,P1,K2,P2,......,Kn,Pn)。其中:

       a)   Ki (i=1...n)为关键字,且关键字按顺序升序排序K(i-1)< Ki。

       b)   Pi为指向子树根的接点,且指针P(i-1)指向子树种所有结点的关键字均小于Ki,但都大于K(i-1)。

       c)   关键字的个数n必须满足: [ceil(m / 2)-1]<= n <= m-1。

下图给出了典型的3阶B-树

B-树中的每个结点根据实际情况可以包含大量的关键字信息和分支(当然是不能超过磁盘块的大小,根据磁盘驱动(disk drives)的不同,一般块的大小在1k~4k左右);这样树的深度降低了,这就意味着查找一个元素只要很少结点从外存磁盘中读入内存,很快访问到要查找的数据

B-树定义的结点

#define MAXM 10                /*定义B-树的最大的阶数*/
typedef int KeyType;           /*KeyType为关键字类型*/
typedef struct BTNode          /*B-树结点类型定义*/
{ 
    int keynum;                /*结点当前拥有的关键字的个数*/
    KeyType key[MAXM];         /*key[1..keynum]存放关键字,key[0]不用*/
    struct BTNode *parent;     /*双亲结点指针*/
    struct BTNode *ptr[MAXM];  /*孩子结点指针数组ptr[0..keynum]*/
}BTTree;

2.基本操作

 1)B-树的插入操作(重点判断是否满足n<=m-1)--分裂

      a.利用前述的B-树的查找算法查找关键字的插入位置。若找到,则说明该关键字已经存在,直接返回。否则查找操作必失败于某个最低层的非终端结点上。

      b.判断该结点是否还有空位置。即判断该结点的关键字总数是否满足n<=m-1。若满足,则说明该结点还有空位置,直接把关键字k插入到该结点的合适位置上。若不满足,说明该结点己没有空位置,需要把结点分裂成两个。

分裂的方法是:生成一新结点。把原结点上的关键字和k按升序排序后,从中间位置把关键字(不包括中间位置的关键字)分成两部分。左部分所含关键字放在旧结点中,右部分所含关键字放在新结点中,中间位置的关键字连同新结点的存储位置插入到父结点中。如果父结点的关键字个数也超过(m-1),则要再分裂,再往上插。直至这个过程传到根结点为止。

2).B-树的删除操作(重点判断删除所在结点及其兄弟结点,父结点中n>ceil(m/2)-1,n=ceil(m/2)-1,n<ceil(m/2)-1)

在B-树上删除关键字K的过程也可以分为两步完成

a.利用前述的B-树的查找算法找出该关键字所在的结点。然后根据 k所在结点是否为叶子结点有不同的处理方法。

b.若该结点为非叶结点,且被删关键字为该结点中第i个关键字key[i],则可从指针son[i]所指的子树中找出最小关键字Y,代替key[i]的位置,然后在叶结点中删去Y。【每个非终端结点中包含有n个关键字信息: (n,P0,K1,P1,K2,P2,......,Kn,Pn)。】因此,把在非叶结点删除关键字k的问题就变成了删除叶子结点中的关键字的问题了。

 

后补:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/25/2608412.html

 

posted @ 2016-05-05 10:15  风清扬二代目  阅读(143)  评论(0)    收藏  举报