1. 程式人生 > >B-樹(B樹)詳解

B-樹(B樹)詳解

具體講解之前,有一點,再次強調下:B-樹,即為B樹。因為B樹的原英文名稱為B-tree,而國內很多人喜歡把B-tree譯作B-樹,其實,這是個非常不好的直譯,很容易讓人產生誤解。如人們可能會以為B-樹是一種樹,而B樹又是一種樹。而事實上是,B-tree就是指的B樹。特此說明。


1、B-樹(B樹)的基本概念
B-樹中所有結點中孩子結點個數的最大值成為B-樹的階,通常用m表示,從查詢效率考慮,一般要求m>=3。一棵m階B-樹或者是一棵空樹,或者是滿足以下條件的m叉樹。
1)每個結點最多有m個分支(子樹);而最少分支數要看是否為根結點,如果是根結點且不是葉子結點,則至少要有兩個分支,非根非葉結點至少有ceil(m/2)個分支,這裡ceil代表向上取整。
2)如果一個結點有n-1個關鍵字,那麼該結點有n個分支。這n-1個關鍵字按照遞增順序排列。
3)每個結點的結構為:


nk1k2...kn
p0p1p2...pn
其中,n為該結點中關鍵字的個數;ki為該結點的關鍵字且滿足ki<ki+1;pi為該結點的孩子結點指標且滿足pi所指結點上的關鍵字大於ki且小於ki+1,p0所指結點上的關鍵字小於k1,pn所指結點上的關鍵字大於kn。


4)結點內各關鍵字互不相等且按從小到大排列。
5)葉子結點處於同一層;可以用空指標表示,是查詢失敗到達的位置。


注:平衡m叉查詢樹是指每個關鍵字的左側子樹與右側子樹的高度差的絕對值不超過1的查詢樹,其結點結構與上面提到的B-樹結點結構相同,由此可見,B-樹是平衡m叉查詢樹,但限制更強,要求所有葉結點都在同一層。


光看上面的解釋可能大家對B-樹理解的還不是那麼透徹,下面我們用一個例項來進行講解。




上面的圖片顯示了一棵B-樹,最底層的葉子結點沒有顯示。我們對上面提到的5條特點進行逐條解釋:
1)結點的分支數等於關鍵字數+1,最大的分支數就是B-樹的階數,因此m階的B-樹中結點最多有m個分支,所以可以看到,上面的一棵樹是一個5-階B-樹。
2)因為上面是一棵5階B-樹,所以非根非葉結點至少要有ceil(5/2)=3個分支。根結點可以不滿足這個條件,圖中的根結點有兩個分支。
3)如果根結點中沒有關鍵字就沒有分支,此時B-樹是空樹,如果根結點有關鍵字,則其分支數比大於或等於2,因為分支數等於關鍵字數+1.
4)上圖中除根結點外,結點中的關鍵字個數至少為2,因為分支數至少為3,分支數比關鍵字數多1,還可以看出結點內關鍵字都是有序的,並且在同一層中,左邊結點內所有關鍵字均小於右邊結點內的關鍵字,例如,第二層上的兩個結點,左邊結點內的關鍵字為15,26,他們均小於右邊結點內的關鍵字39和45.
B-樹一個很重要的特徵是,下層結點內的關鍵字取值總是落在由上層結點關鍵字所劃分的區間內,具體落在哪個區間內可以由指向它的指標看出。例如,第二層最左邊的結點內的關鍵字劃分了三個區間,小於15,15到26,大於26,可以看出其下層中最左邊結點內的關鍵字都小於15,中間結點的關鍵字在15和26之間,右邊結點的關鍵字大於26.
5)上圖中葉子結點都在第四層上,代表查詢不成功的位置。


2、B-樹的查詢操作
B-樹的查詢很簡單,是二叉排序樹的擴充套件,二叉排序樹是二路查詢,B-樹是多路查詢,因為B-樹結點內的關鍵字是有序的,在結點內進行查詢時除了順序查詢外,還可以用折半查詢來提升效率。B-樹的具體查詢步驟如下(假設查詢的關鍵字為key):
1)先讓key與根結點中的關鍵字比較,如果key等於k[i](k[]為結點內的關鍵字陣列),則查詢成功
2)若key<k[1],則到p[0]所指示的子樹中進行繼續查詢(p[]為結點內的指標陣列),這裡要注意B-樹中每個結點的內部結構。
3)若key>k[n],則道p[n]所指示的子樹中繼續查詢。
4)若k[i]<key<k[i+1],則沿著指標p[I]所指示的子樹繼續查詢。
5)如果最後遇到空指標,則證明查詢不成功。


拿上面的二叉樹進行舉例,比如我們想要查詢關鍵字42,下圖加粗的部分顯示了查詢的路徑:






3、B-樹的插入
與二叉排序樹一樣,B-樹的建立過程也是將關鍵字逐個插入到樹中的過程。
在進行插入之前,要確定一下每個結點中關鍵字個數的範圍,如果B-樹的階數為m,則結點中關鍵字個數的範圍為ceil(m/2)-1 ~ m-1個。
對於關鍵字的插入,需要找到插入位置。在B-樹的查詢過程中,當遇到空指標時,則證明查詢不成功,同時也找到了插入位置,即根據空指標可以確定在最底層非葉結點中的插入位置,為了方便,我們稱最底層的非葉結點為終端結點,由此可見,B-樹結點的插入總是落在終端結點上。在插入過程中有可能破壞B-樹的特徵,如新關鍵字的插入使得結點中關鍵字的個數超過規定個數,這是要進行結點的拆分。
接下來,我們以關鍵字序列{1,2,6,7,11,4,8,13,10,5,17,9,16,20,3,12,14,18,19,15}建立一棵5階B-樹,我們將詳細體會B-樹的插入過程。
(1)確定結點中關鍵字個數範圍
由於題目要求建立5階B-樹,因此關鍵字的個數範圍為2~4
(2)根結點最多可以容納4個關鍵字,依次插入關鍵字1、2、6、7後的B-樹如下圖所示:




(3)當插入關鍵字11的時候,發現此時結點中關鍵字的個數變為5,超出範圍,需要拆分,去關鍵字陣列中的中間位置,也就是k[3]=6,作為一個獨立的結點,即新的根結點,將關鍵字6左、右關鍵字分別做成兩個結點,作為新根結點的兩個分支,此時樹如下圖所示:




(4)新關鍵字總是插在葉子結點上,插入關鍵字4、8、13之後樹為:




(5)關鍵字10需要插入在關鍵字8和11之間,此時又會出現關鍵字個數超出範圍的情況,因此需要拆分。拆分時需要將關鍵字10納入根結點中,並將10左右的關鍵字做成兩個新的結點連在根結點上。插入關鍵字10並經過拆分操作後的B-樹如下圖:




(6)插入關鍵字5、17、9、16之後的B-樹如圖所示:




(7)關鍵字20插入在關鍵字17以後,此時會造成結點關鍵字個數超出範圍,需要拆分,方法同上,樹為:




(8)按照上述步驟依次插入關鍵字3、12、14、18、19之後B-樹如下圖所示:




(9)插入最後一個關鍵字15,15應該插入在14之後,此時會出現關鍵字個數超出範圍的情況,則需要進行拆分,將13併入根結點,13併入根結點之後,又使得根結點的關鍵字個數超出範圍,需要再次進行拆分,將10作為新的根結點,並將10左、右關鍵字做成兩個新結點連線到新根結點的指標上,這種插入一個關鍵字之後出現多次拆分的情況稱為連鎖反應,最終形成的B-樹如下圖所示:




4、B-樹的刪除
對於B-樹關鍵字的刪除,需要找到待刪除的關鍵字,在結點中刪除關鍵字的過程也有可能破壞B-樹的特性,如舊關鍵字的刪除可能使得結點中關鍵字的個數少於規定個數,這是可能需要向其兄弟結點借關鍵字或者和其孩子結點進行關鍵字的交換,也可能需要進行結點的合併,其中,和當前結點的孩子進行關鍵字交換的操作可以保證刪除操作總是發生在終端結點上。


我們用剛剛生成的B-樹作為例子,一次刪除8、16、15、4這4個關鍵字。
(1)刪除關鍵字8、16。關鍵字8在終端結點上,並且刪除後其所在結點中關鍵字的個數不會少於2,因此可以直接刪除。關鍵字16不在終端結點上,但是可以用17來覆蓋16,然後將原來的17刪除掉,這就是上面提到的和孩子結點進行關鍵字交換的操作。這裡不能用15和16進行關鍵字交換,因為這樣會導致15所在結點中關鍵字的個數小於2。因此,刪除8和16之後B-樹如下圖所示:




(2)刪除關鍵字15,15雖然也在終端結點上,但是不能直接刪除,因為刪除後當前結點中關鍵字的個數小於2。這是需要向其兄弟結點借關鍵字,顯然應該向其右兄弟來借關鍵字,因為左兄弟的關鍵字個數已經是下限2.借關鍵字不能直接將18移到15所在的結點上,因為這樣會使得15所在的結點上出現比17大的關鍵字,所以正確的借法應該是先用17覆蓋15,在用18覆蓋原來的17,最後刪除原來的18,刪除關鍵字15後的B-樹如下圖所示:




(3)刪除關鍵字4,4在終端結點上,但是此時4所在的結點的關鍵字個數已經到下限,需要借關鍵字,不過可以看到其左右兄弟結點已經沒有多餘的關鍵字可借。所以就需要進行關鍵字的合併。可以先將關鍵字4刪除,然後將關鍵字5、6、7、9進行合併作為一個結點連結在關鍵字3右邊的指標上,也可以將關鍵字1、2、3、5合併作為一個結點連結在關鍵字6左邊的指標上,如下圖所示:




顯然上述兩種情況下都不滿足B-樹的規定,即出現了非根的雙分支結點,需要繼續進行合併,合併後的B-樹如下圖所示:




有時候刪除的結點不在終端結點上,我們首先需要將其轉化到終端結點上,然後再按上面的各種情況進行刪除。在講述這種情況下的刪除方法之前,要引入一個相鄰關鍵字的概念,對於不在終端結點的關鍵字a,它的相鄰關鍵字為其左子樹中值最大的關鍵字或者其右子樹中值最小的關鍵字。找a的相鄰關鍵字的方法為:沿著a的左指標來到其子樹根結點,然後沿著根結點中最右端的關鍵字的右指標往下走,用同樣的方法一直走到葉結點上,葉結點上的最右端的關鍵字即為a的相鄰關鍵字(這裡找的是a左邊的相鄰關鍵字,我們可以用同樣的思路找到a右邊的相鄰關鍵字)。可以看到下圖中a的相鄰關鍵字是d和e,要刪除關鍵字a,可以用d來取代a,然後按照上面的情況刪除葉子結點上的d即可。


6、B-樹的應用
為了將大型資料庫檔案儲存在硬碟上,以減少訪問硬碟次數為目的,在此提出了一種平衡多路查詢樹——B-樹結構。由其效能分析可知它的檢索效率是相當高的 為了提高 B-樹效能’還有很多種B-樹的變型,力圖對B-樹進行改進,比如B+樹。


作者:wwlovett
連結:https://www.jianshu.com/p/7dedb7ebe033
來源:簡書
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。