1. 程式人生 > >圖解B樹和B+樹的插入和刪除操作

圖解B樹和B+樹的插入和刪除操作

一,    M階B+樹的定義(M階是指一個節點最多能擁有的孩子數,M>2):

圖1.1 3階B+樹

        (1)根結點只有1個,分支數量範圍[2,m]。

        (2)除根以外的非葉子結點,每個結點包含分支數範圍[[m/2],m],其中[m/2]表示取大於m/2的最小整數。

        (3)所有非葉子節點的關鍵字數目等於它的分支數量。

        (4) 所有葉子節點都在同一層,且關鍵字數目範圍是[[m/2],m],其中[m/2]表示取大於m/2的最小整數。

        (5)所有非葉子節點的關鍵字可以看成是索引部分,這些索引等於其子樹(根結點)中的最大(或最小)關鍵字。例如一個非葉子節點包含資訊: (n,A0,K0, A1,K1,……,Kn,An),其中Ki為關鍵字,Ai為指向子樹根結點的

指標,n表示關鍵字個數。即Ai所指子樹中的關鍵字均小於或等於Ki,而Ai+1所指的關鍵字均大於Ki(i=1,2,……,n)。

        (6)葉子節點包含全部關鍵字的資訊(非葉子節點只包含索引),且葉子結點中的所有關鍵字依照大小順序連結(所以一個B+樹通常有兩個頭指標,一個是指向根節點的root,另一個是指向最小關鍵字的sqt)。

二,    3階B+樹的插入舉例:

l  例1:

往下圖的3階B+樹中插入關鍵字9

首先查詢9應插入的葉節點(最左下角的那一個),插入發現沒有破壞B+樹的性質,完畢。插完如下圖所示:

l  例2:

往下圖的3階B+樹插入20

首先查詢20應插入的葉節點(第二個葉子節點),插入,如下圖

發現第二個葉子節點已經破壞了B+樹的性質,則把之分解成[20 21], [37 44]兩個,並把21往父節點移,如下圖

發現父節點也破壞了B+樹的性質,則把之再分解成[15 21], [44 59]兩個,並把21往其父節點移,如下圖

這次沒有破壞B+樹的性質(如果還是不滿足B+樹的性質,可以遞迴上去,直到滿足為至),插入完畢。

l  例3:

往下圖的3階B+樹插入100

首先查詢100應插入的葉節點(最後一個節點), 插入,如下圖

修改其所有父輩節點的鍵值為100(只有插入比當前樹的最大數大的數時要做此步),如下圖

然後重複Eg.2的方法拆分節點,最後得

三,    3階B+樹的刪除舉例:

l  例1:

刪除下圖3階B+樹的關鍵字91

首先找到91所在葉節點(最後一個節點),刪除之,如下圖

沒有破壞B+樹的性質,刪除完畢

l  例2:

刪除下圖3階B+樹的關鍵字97

首先找到97所在葉節點(最後一個節點),刪除之,然後修改該節點的父輩的鍵字為91(只有刪除樹中最大數時要做此步),如下圖

l  例3:

刪除下圖3階B+樹的關鍵字51

首先找到51所在節點(第三個節點),刪除之,如下圖

破壞了B+樹的性質,從該節點的兄弟節點(左邊或右邊)借節點44,並修改相應鍵值,判斷沒有破壞B+樹,完畢,如下圖

l  例4:

刪除下圖3階B+樹的關鍵字59

首先找到59所在葉節點(第三個節點),刪除之,如下圖

破壞B+樹性質,嘗試借節點,無效(因為左兄弟節點被借也會破壞B+樹性質),合併第二第三葉節點並調整鍵值,如下圖

完畢。

l  例5:

刪除下圖3階B+樹的關鍵字63

首先找到63所在葉節點(第四個節點),刪除之,如下圖

合併第四五葉節點並調整鍵值,如下圖

發現第二層的第二個節點不滿足B+樹性質,從第二層的第一個節點借59,並調整鍵值,如下圖

這裡的B樹,也就是英文中的B-Tree,一個 m 階的B樹滿足以下條件:

  1. 每個結點至多擁有m棵子樹;
  2. 根結點至少擁有兩顆子樹(存在子樹的情況下);
  3. 除了根結點以外,其餘每個分支結點至少擁有 m/2 棵子樹;
  4. 所有的葉結點都在同一層上;
  5. 有 k 棵子樹的分支結點則存在 k-1 個關鍵碼,關鍵碼按照遞增次序進行排列;
  6. 關鍵字數量需要滿足ceil(m/2)-1 <= n <= m-1;

舉個栗子:

B樹上大部分的操作所需要的磁碟存取次數和B樹的高度是成正比的,在B樹中可以檢查多個子結點,由於在一棵樹中檢查任意一個結點都需要一次磁碟訪問,所以B樹避免了大量的磁碟訪問。

操作

既然是樹,那麼必不可少的操作就是插入和刪除,這也是B樹和其它資料結構不同的地方,當然了,還有必不可少的搜尋,分享一個對B樹的操作進行視覺化的網址,它是由usfca提供的。

假定對高度為h的m階B樹進行操作。

插入

新結點一般插在第h層,通過搜尋找到對應的結點進行插入,那麼根據即將插入的結點的數量又分為下面幾種情況。

  • 如果該結點的關鍵字個數沒有到達m-1個,那麼直接插入即可;
  • 如果該結點的關鍵字個數已經到達了m-1個,那麼根據B樹的性質顯然無法滿足,需要將其進行分裂。分裂的規則是該結點分成兩半,將中間的關鍵字進行提升,加入到父親結點中,但是這又可能存在父親結點也滿員的情況,則不得不向上進行回溯,甚至是要對根結點進行分裂,那麼整棵樹都加了一層。

其過程如下:

刪除

同樣的,我們需要先通過搜尋找到相應的值,存在則進行刪除,需要考慮刪除以後的情況,

  • 如果該結點擁有關鍵字數量仍然滿足B樹性質,則不做任何處理;
  • 如果該結點在刪除關鍵字以後不滿足B樹的性質(關鍵字沒有到達ceil(m/2)-1的數量),則需要向兄弟結點借關鍵字,這有分為兄弟結點的關鍵字數量是否足夠的情況。
    • 如果兄弟結點的關鍵字足夠借給該結點,則過程為將父親結點的關鍵字下移,兄弟結點的關鍵字上移;
    • 如果兄弟結點的關鍵字在借出去以後也無法滿足情況,即之前兄弟結點的關鍵字的數量為ceil(m/2)-1,借的一方的關鍵字數量為ceil(m/2)-2的情況,那麼我們可以將該結點合併到兄弟結點中,合併之後的子結點數量少了一個,則需要將父親結點的關鍵字下放,如果父親結點不滿足性質,則向上回溯;
  • 其餘情況參照BST中的刪除。

其過程如下:

B樹和B+樹的區別

這都是由於B+樹和B具有這不同的儲存結構所造成的區別,以一個m階樹為例。

  1. 關鍵字的數量不同;B+樹中有m個分支節點那麼該節點就有m個關鍵字,其關鍵字只是起到了一個索引的作用,但是B樹雖然也有m個子結點,但是其只擁有m-1個關鍵字。
  2. 儲存的位置不同;B+樹中的資料都儲存在葉子結點上,也就是其所有葉子結點的資料組合起來就是完整的資料,但是B樹的資料儲存在每一個結點中,並不僅僅儲存在葉子結點上。B樹適用於檔案儲存,B+樹適合於索引儲存,查詢資料時不需要遍歷整個樹,只是需要在對應的區間內查詢。而B樹需要一遍中序遍歷
  3. 分支結點的構造不同;B+樹的分支結點僅僅儲存著關鍵字資訊和兒子的指標(這裡的指標指的是磁碟塊的偏移量),也就是說內部結點僅僅包含著索引資訊。
  4. 查詢不同;B樹在找到具體的數值以後,則結束,而B+樹則需要通過索引找到葉子結點中的資料才結束,也就是說B+樹的搜尋過程中走了一條從根結點到葉子結點的路徑。