圖解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為指向子樹根結點的
(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樹滿足以下條件:
- 每個結點至多擁有m棵子樹;
- 根結點至少擁有兩顆子樹(存在子樹的情況下);
- 除了根結點以外,其餘每個分支結點至少擁有 m/2 棵子樹;
- 所有的葉結點都在同一層上;
- 有 k 棵子樹的分支結點則存在 k-1 個關鍵碼,關鍵碼按照遞增次序進行排列;
- 關鍵字數量需要滿足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階樹為例。
- 關鍵字的數量不同;B+樹中有m個分支節點那麼該節點就有m個關鍵字,其關鍵字只是起到了一個索引的作用,但是B樹雖然也有m個子結點,但是其只擁有m-1個關鍵字。
- 儲存的位置不同;B+樹中的資料都儲存在葉子結點上,也就是其所有葉子結點的資料組合起來就是完整的資料,但是B樹的資料儲存在每一個結點中,並不僅僅儲存在葉子結點上。B樹適用於檔案儲存,B+樹適合於索引儲存,查詢資料時不需要遍歷整個樹,只是需要在對應的區間內查詢。而B樹需要一遍中序遍歷
- 分支結點的構造不同;B+樹的分支結點僅僅儲存著關鍵字資訊和兒子的指標(這裡的指標指的是磁碟塊的偏移量),也就是說內部結點僅僅包含著索引資訊。
- 查詢不同;B樹在找到具體的數值以後,則結束,而B+樹則需要通過索引找到葉子結點中的資料才結束,也就是說B+樹的搜尋過程中走了一條從根結點到葉子結點的路徑。