1. 程式人生 > >6.3.1 B樹及其基本操作

6.3.1 B樹及其基本操作

B樹,又稱多路平衡查詢樹,B樹中所有節點的孩子結點數的最大值成為B樹的階,通常用m表示。一棵m階B樹或為空樹,或為滿足如下特性的m叉樹:

1)樹中每個結點至多有m棵子樹(即至多含有m-1個關鍵字)。

2)若根結點不是終端結點,則至少有兩棵子樹

3)除根結點外的所有非葉結點至少有【m/2】(向上取整)棵子樹(即至少含有【m/2】-1個關鍵字)

4)所有非葉結點的結構如下:

n P0 K1 P1 k2 P2 ... Kn Pn

其中,Ki(i=1,2,...,n)為結點的關鍵字,且滿足K1<K2<···<Kn;Pi(i=0,1,···,n)為指向子樹根結點的指標,且指標Pi-1所指向子樹中所有結點的關鍵字均小於Ki,Pi所指子樹中所有結點的關鍵字均大於Ki,n( 向下取整【m/2】-1<=n<=m-1 )為結點中關鍵字的個數。

5)所有的葉節點都出現在同一層次上,並且不帶資訊(可以看做是外部結點或者類似於折半查詢判定樹的查詢失敗結點,實際上這些結點不存在,指向這些結點的指標為空)。

B樹是所有結點的平衡因子均等於0的多路查詢樹,其中底層方形結點表示葉結點,在這些結點中沒有儲存任何資訊。

1.B樹的高度(磁碟存取次數)

由下一節可知,B樹中的大部分操作所需的磁碟存取次數與B樹的高度成正比。

下面來分析B樹在不同的情況下的高度。當然,首先應明確B樹的高度不包括最後的不帶任何資訊的葉結點所處的那一層。

如果n>=1,則對任意一棵包含n個關鍵字,高度為h,階數為m的B樹:

1)因為B樹中每個結點最多有m棵子樹,m-1個關鍵字,所以在一棵高度為h的m階B樹中關鍵字的個數應滿足n<=(1+m+m^2+……+m^(h-1))=m^h-1。因此有

h>=logm  (n+1)(由關鍵字個數計算B樹的最小高度)
2)若讓每個結點的關鍵字個數達到最少,則容納同樣多關鍵字的B樹的高度可達到最大。

由B樹定義:

第一層至少有1個結點;

第二層至少有2個結點;

除根結點以外的每個非終端結點至少有【m/2】(向下取整)棵子樹,則第三層至少有2*【m/2】(向下取整)個結點

……

第h+1層至少有2*(【m/2】向下取整)^(h-1)個結點,注意到第h+1層是不包含任何資訊的葉結點。

對於關鍵字個數為n的B樹,葉結點即查詢不成功的結點為n+1,

由此有n+1>2*([m/2]向上取整)^(h-1)

h<=log[m/2](向上取整)((n+1)/2)+1(由關鍵字個數計算B樹的最大高度)

假設一棵3階B樹,共有8個關鍵字,則其高度範圍為2<=h<=3.17

2.B樹的查詢

在B樹在進行查詢二叉樹很相似,只是每個結點都是多個關鍵字的有序表,在每個結點上所做的不是兩路分支決定,而是根據該結點的子樹所做的多路分支決定。

B樹的查詢包含兩個基本操作:

①在B樹中找結點;

②在結點中找關鍵字。

由於B樹常儲存在磁碟上,則前一個查詢操作是在磁碟上進行的,而後一個操作是在記憶體中進行的,即在找到目標結點後,先將結點中的資訊讀入記憶體,然後再順序查詢法或折半查詢法查詢等於k的關鍵字。

在B樹上查詢到某個結點後,先在有序表中進行查詢,若找到則查詢成功,否則按照對應的指標資訊到所指的子樹中查詢。當查詢到葉結點時(對應的指標為空指標),則說明樹中沒有對應的關鍵字,查詢失敗。

3.B樹的插入

與二叉查詢樹的插入操作相比,B樹的插入操作要複雜得多。在二叉查詢樹中,僅需查詢到需插入的終端結點的位置。但是,在B樹中找到插入的位置後,並不能簡單地將其加到終端結點中去,因為此時可能導致整棵樹不再滿足B樹中定義的要求。將關鍵字key插入到B樹的過程如下:

1)定位:利用前述的B樹查詢演算法,找出插入該關鍵字的最底層中某個非葉結點(注意,B樹中的插入關鍵字一定是插入在最底層中的某個非葉子結點內)

2)插入:在B樹中,每個非失敗結點的關鍵字個數都在【(m/2)向上取整-1,m-1】之間。當插入後的結點關鍵字個數小於m,則可以直接插入;插入後檢查被插入結點內關鍵字的個數,當插入後的結點關鍵字個數大於m-1時,則必須對結點進行分裂。

分裂的方法是:取一個新結點,將插入key後的原結點從中間位置將其中的關鍵字分為兩部分,左部分包含的關鍵字放在原結點中,右部分包含的關鍵字放在新的結點中,中間位置(【m/2】向上取整)的結點插入到原結點的父結點中。若此時導致其父結點的關鍵字個數也超過了上限,則繼續進行這種分裂操作,直到這個過程傳到根結點為止,這樣導致B樹高度增1。


4.B樹的刪除

B樹中的刪除操作與插入操作類似,但要稍微複雜些,要使刪除後的結點的關鍵字個數>=([m/2]向下取整)-1,因此涉及結點的合併問題。

當所刪除的關鍵字k不在終端結點(最底層非葉結點)中時,有下列幾種情況:

1)如果小於k的子樹中關鍵字個數>([m/2]向上取整)-1,則找出k的的前驅值K',並且用K'來取代k,再遞迴地刪除K'即可。

2)如果大於k的子樹中關鍵字個數>([m/2]向上取整)-1,則找出k的的後繼值K',並且用K'來取代k,再遞迴地刪除K'即可。

3)如果前後兩個子樹中關鍵字個數均為([m/2]向上取整)-1,則直接將兩個子結點合併,直接刪除k即可。

當被刪除的關鍵字在終端結點(最低層非葉結點)中時,有下列幾種情況:

1)直接刪除關鍵字:若被刪除關鍵字所在結點的關鍵字個數>【m/2】(向上取整)-1,表明刪除該關鍵字後仍滿足B樹的定義,則直接刪去該關鍵字。

2)兄弟夠借:若被刪除關鍵字所在結點刪除前的關鍵字個數=【m/2】(向上取整)-1,且與此結點相鄰的左(右)兄弟結點的關鍵字個數>=【m/2】(向上取整),需要調整該結點左(右)兄弟結點及其雙親結點(父子換位法),以達到新的平衡。

3)兄弟不夠借:若被刪除關鍵字所在結點刪除前的關鍵字個數=【m/2】(向上取整)-1,且此時與該結點相鄰的左(右)兄弟結點的關鍵字個數=【m/2】(向上取整)-1,則將關鍵字刪除後,將左(右)兄弟結點及雙親結點中的關鍵字合併。

在合併的過程中,雙親結點的關鍵字個數會減少。若其雙親結點是根結點並且關鍵字個數減少至0(根結點關鍵字個數為1時,有兩棵子樹),則直接將根結點刪除,合併後的新結點成為根;若雙親結點不是根結點,且關鍵字個數減少至【m/2】-2,又要與它自己的兄弟結點進行調整或合併操作,並重覆上述步驟,直至符合B樹的要求為止。