B 樹是為了磁盤或其它存儲設備而設計的一種多叉(下面你會看到,相對于二叉,B樹每個內結點有多個分支,即多叉)平衡查找樹。
B 樹又叫平衡多路查找樹。一棵m階的B 樹 (m叉樹)的特性如下:
- 樹中每個結點最多含有m個孩子(m>=2);
- 除根結點和葉子結點外,其它每個結點至少有[ceil(m / 2)]個孩子(其中ceil(x)是一個取上限的函數);
- 若根結點不是葉子結點,則至少有2個孩子(特殊情況:沒有孩子的根結點,即根結點為葉子結點,整棵樹只有一個根節點);
- 所有葉子結點都出現在同一層,葉子結點不包含任何關鍵字信息(可以看做是外部接點或查詢失敗的接點,實際上這些結點不存在,指向這些結點的指針都為null);
- 每個非終端結點中包含有n個關鍵字信息: (P1,K1,P2,K2,P3,......,Kn,Pn+1)。其中:
???????a) ??Ki (i=1...n)為關鍵字,且關鍵字按順序升序排序K(i-1)< Ki。?
???????b) ??Pi為指向子樹根的接點,且指針P(i)指向子樹種所有結點的關鍵字均小于Ki,但都大于K(i-1)。?
???????c) ??關鍵字的個數n必須滿足: [ceil(m / 2)-1]<= n <= m-1。
?
?
來模擬下查找文件29的過程:
- ???(1) 根據根結點指針找到文件目錄的根磁盤塊1,將其中的信息導入內存。【磁盤IO操作1次】
- ???(2) 此時內存中有兩個文件名17,35和三個存儲其他磁盤頁面地址的數據。根據算法我們發現17<29<35,因此我們找到指針p2。
- ???(3) 根據p2指針,我們定位到磁盤塊3,并將其中的信息導入內存。【磁盤IO操作2次】
- ???(4) 此時內存中有兩個文件名26,30和三個存儲其他磁盤頁面地址的數據。根據算法我們發現26<29<30,因此我們找到指針p2。
- ???(5) 根據p2指針,我們定位到磁盤塊8,并將其中的信息導入內存。【磁盤IO操作3次】
- ???(6) 此時內存中有兩個文件名28,29。根據算法我們查找到文件29,并定位了該文件內存的磁盤地址。
插入操作
生 成從空樹開始,逐個插入關鍵字。但是由于B_樹節點關鍵字必須大于等于[ceil(m/2)-1],所以每次插入一個關鍵字不是在樹中添加一個葉子結點, 而是首先在最底層的某個非終端節點中添加一個“關鍵字”,該結點的關鍵字不超過m-1,則插入完成;否則要產生結點的“分裂”,將一半數量的關鍵字元素分裂到新的其相鄰右結點中,中間關鍵字元素上移到父結點中。
1、咱們通過一個實例來逐步講解下。插入以下字符字母到一棵空的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節點中。這樣具體插入操作的完成。
?