B-树的生成是从空树起,逐个插入关键字而得到的。
(1)插入关键字K的方法
首先在树中查找K,若找到则直接返回(假设不处理相同关键字的插入);否则查找操作必失败于某个叶子上,然后将K插入该叶子中。若该叶子结点原来是非满(指keynum<Max,即结点中原有的关键字总数小于m-1)的,则插入K后并未破坏B-树的性质,故插入K后即完成了插入操作;若该结点原为满,则K插入后keynum=m,违反B-树性质(3),故须调整使其维持B-树性质不变。
调整操作:
将违反性质(3)的结点以中间位置上的关键字 为划分点,将该
结点(不妨设是*current):
(m,P0,K1,P1,…,Km,Pm) //Ki表示key[i],Pi表示son[i]
"分裂"为两个结点:
并将中间关键字 (和新结点指针new一起插入到*current的双亲*parent中。
注意:
①当m为奇数时,分裂后的两结点中的关键字数目相同,均是半满;
②若m为偶数,则*new中关键字数比*current中关键字数多1。
其中i表示key和son向量的下标。
注意:
当和新结点的地址一起插入已满的双亲后,双亲也要做分裂操作。最坏情况是,从被插入的叶子到根的路径上各结点均是满结点,此时,插入过程中的分裂操作一直向上传播到根。当根分裂时,因根没有双亲,故需建立一个新的根,此时树长高一层。
(2)B-树的生成
由空树开始,逐个插入关键字,即可生成B-树。
【例】以关键字序列(a,g,f,b,k,d,h,m,i,e, s,i,r,x,c,l,n,t,u,p)建立一棵5阶B-树的生长过程【参见动画演示】
注意:
①当一结点分裂时所产生的两个结点大约是半满的,这就为后续的插入腾出了较多的空间,尤其是当m较大时,往这些半满的空间中插入新的关键字不会很快引起新的分裂。
②向上插人的关键字总是分裂结点的中间位置上的关键字,它未必是正待插入该分裂结点的关键字。因此,无论按何次序插入关键字序列,树都是平衡的。