B樹的插入和刪除

B樹的插入和刪除

寫這篇文章之前一直認爲B數和B-樹是兩種不同的樹,實際上B-tree樹即B樹,B即Balanced,平衡的意思。因爲B樹的原英文名稱爲B-tree,而很多人喜歡把B-tree譯作B-樹,其實,這是個非常不好的直譯,很容易讓人產生誤解。如人們可能會以爲B-樹是一種樹,而B樹又是另一種樹。而事實上是,B-tree就是指的B樹。
一棵m階B樹(balanced tree of order m)是一棵平衡的m路搜索樹。它或者是空樹,或者是滿足下列性質的樹:
1、根結點至少有兩個子女;
2、每個非根節點所包含的關鍵字個數 j 滿足:┌m/2┐ - 1 <= j <= m - 1;
3、除根結點以外的所有結點(不包括葉子結點)的度數正好是關鍵字總數加1,故內部子樹個數 k 滿足:┌m/2┐ <= k <= m ;
4、所有的葉子結點都位於同一層。
在B-樹中,每個結點中關鍵字從小到大排列,並且當該結點的孩子是非葉子結點時,該k-1個關鍵字正好是k個孩子包含的關鍵字的值域的分劃。
因爲葉子結點不包含關鍵字,所以可以把葉子結點看成在樹裏實際上並不存在外部結點,指向這些外部結點的指針爲空,葉子結點的數目正好等於樹中所包含的關鍵字總個數加1。
B-樹中的一個包含n個關鍵字,n+1個指針的結點的一般形式爲: (n,P0,K1,P1,K2,P2,…,Kn,Pn),其中,Ki爲關鍵字,K1<K2<…<Kn,Pi是指向包括Ki到Ki+1之間的關鍵字的子樹指針

B樹

  那好!下面咱們以一棵5階(即樹中任一結點至多含有4個關鍵字,5棵子樹)B樹實例進行插入刪除操作講解(如下圖所示):


插入(insert)操作
插入一個元素時,首先在B樹中是否存在,如果不存在,即在葉子結點處結束,然後在葉子結點中插入該新的元素,注意:如果葉子結點空間足夠,這裏需要向右移動該葉子結點中大於新插入關鍵字的元素,如果空間滿了以致沒有足夠的空間去添加新的元素,則將該結點進行“分裂”,將一半數量的關鍵字元素分裂到新的其相鄰右結點中,中間關鍵字元素上移到父結點中(當然,如果父結點空間滿了,也同樣需要“分裂”操作),而且當結點中關鍵元素向右移動了,相關的指針也需要向右移。如果在根結點插入新元素,空間滿了,則進行分裂操作,這樣原來的根結點中的中間關鍵字元素向上移動到新的根結點中,因此導致樹的高度增加一層。如下圖所示:

1、OK,下面咱們通過一個實例來逐步講解下。插入以下字符字母到一棵空的B 樹中(非根結點關鍵字數小了(小於2個)就合併,大了(超過4個)就分裂):C N G A H E K Q M F W L T Z D P R X Y S,首先,結點空間足夠,4個字母插入相同的結點中,如下圖:

2、當咱們試着插入H時,結點發現空間不夠,以致將其分裂成2個結點,移動中間元素G上移到新的根結點中,在實現過程中,咱們把A和C留在當前結點中,而H和N放置新的其右鄰居結點中。如下圖:

3、當咱們插入E,K,Q時,不需要任何分裂操作。 如圖:

4、插入M需要一次分裂,注意M恰好是中間關鍵字元素,以致向上移到父節點中。如圖:

5、插入F,W,L,T不需要任何分裂操作。如圖:

6、插入Z時,最右的葉子結點空間滿了,需要進行分裂操作,中間元素T上移到父節點中,注意通過上移中間元素,樹最終還是保持平衡,分裂結果的結點存在2個關鍵字元素。如圖:

7、插入D時,導致最左邊的葉子結點被分裂,D恰好也是中間元素,上移到父節點中,然後字母P,R,X,Y陸續插入不需要任何分裂操作(別忘了,樹中至多5個孩子)。如圖:

8、最後,當插入S時,含有N,P,Q,R的結點需要分裂,把中間元素Q上移到父節點中,但是情況來了,父節點中空間已經滿了,所以也要進行分裂,將父節點中的中間元素M上移到新形成的根結點中,注意以前在父節點中的第三個指針在修改後包括D和G節點中。這樣具體插入操作的完成,下面介紹刪除操作,刪除操作相對於插入操作要考慮的情況多點。如圖:

刪除(delete)操作

(1)刪除操作的兩個步驟
  第一步驟:在樹中查找被刪關鍵字K所在的地點
 第二步驟:進行刪去K的操作

(2)刪去K的操作
 B-樹是二叉排序樹的推廣,中序遍歷B-樹同樣可得到關鍵字的有序序列。任一關鍵字K的中序前趨(後繼)必是K的左子樹(右子樹)中最右(左)下的結點中最後(最前)一個關鍵字。

 若被刪關鍵字K所在的結點非樹葉,則用K的中序前趨(或後繼)K'取代K,然後從葉子中刪去K'。從葉子*x開始刪去某關鍵字K的三種情形爲:

 情形一:若x->keynum>Min,則只需刪去K及其右指針(*x是葉子,K的右指針爲空)即可使刪除操作結束。

注意: Min=【M/2】-1

 情形二:若x->keynum=Min,該葉子中的關鍵字個數已是最小值,刪K及其右指針後會破壞B-樹的性質(3)。若*x的左(或右)鄰兄弟結點*y中的關鍵字數目大於Min,則將*y中的最大(或最小)關鍵字上移至雙親結點*parent中,而將*parent中相應的關鍵字下移至x中。顯然這種移動使得雙親中關鍵字數目不變;*y被移出一個關鍵字,故其keynum減1,因它原大於Min,故減少1個關鍵字後keynum仍大於等於Min;而*x中已移入一個關鍵字,故刪K後*x中仍有Min個關鍵字。涉及移動關鍵字的三個結點均滿足B-樹的性質(3)。 請讀者驗證,上述操作後仍滿足B-樹的性質(1)。移動完成後,刪除過程亦結束。

 情形三:若*x及其相鄰的左右兄弟(也可能只有一個兄弟)中的關鍵字數目均爲最小值Min,則上述的移動操作就不奏效,此時須*x和左或右兄弟合併。不妨設*x有右鄰兄弟*y(對左鄰兄弟的討論與此類似),在*x中刪去K後,將雙親結點*parent中介於*x和*y之間的關鍵字K,作爲中間關鍵字,與並x和*y中的關鍵字一起"合併"爲一個新的結點取代*x和*y。因爲*x和*y原各有Min個關鍵字,從雙親中移人的K'抵消了從*x中刪除的K,故新結點中恰有2Min(即2「m/2」-2≤m-1)個關鍵字,沒有破壞B-樹的性質(3)。但由於K'從雙親中移到新結點後,相當於從*parent中刪去了K',若parent->keynum原大於Min,則刪除操作到此結束;否則,同樣要通過移動*parent的左右兄弟中的關鍵字或將*parent與其 左右兄弟合併的方法來維護B-樹性質。最壞情況下,合併操作會向上傳播至根,當根中只有一個關鍵字時,合併操作將會使根結點及其兩個孩子合併成一個新的根,從而使整棵樹的高度減少一層。如圖: 

參考http://luozhong915127.iteye.com/blog/1638116
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章