一、簡介
名稱:平衡多路查找樹
出現的原因:爲了解決 平衡二叉樹在存儲大量數據時的樹過高的問題。
主要使用場景:數據庫索引
二、定義與性質
基礎1:B樹節點的結構
1)葉子結點結構
葉子節點裏面什麼都沒有,因此不能算是一棵子樹,但它在邏輯上確實是一個結點。可以把它想象成一個空盒子。
2)非葉結點(即不是葉子結點的結點)結構
指針比key(關鍵字)多一個(多一個指針0),因爲key是夾在指針之間的。
這裏的“結點”指的是,它是構成B樹的基本單元,在圖中表示爲這個淡黃色的圓角矩形。即B樹是由多個該結構的結點構成的,這些結點的n可能等於任意正整數。它的形狀就是下圖這樣。
基礎2:B樹的階
B樹中所有節點的孩子結點數(節點的指針數)的最大值稱爲B樹的階。下圖爲一棵3階B樹,因爲該樹的所有結點中,單個節點擁有的孩子結點數(指針數)最多爲3
即key“78”和key“88”所在的節點,擁有三個子樹(三個指針)。
基礎3:終端結點
終端結點是葉子節點的父節點
性質1
在一棵m階B樹中,樹中單個節點最多有m棵子樹(即最多有m-1個key)
解析:這其實和“階的定義”是對應的。換句話說就是:m階B樹單個節點最多有m個指針。那麼那個擁有m個指針的結點自然也就有m-1個key了。
注意:這裏的“最多”(至多),即:子樹最多的那個節點,子樹數目可以比m小。性質1限定了B樹結點內部的最大規模。
性質2
若根結點不是終端結點,則至少有兩棵子樹。
解析:該B樹
若根結點是終端結點
若根結點不是終端結點
但是
性質3
除根結點之外的所有非葉節點至少有[m/2]棵子樹。
解析:即圖中綠色圓角矩形中的每個結點都至少要有[m/2] (m除以2,並向上取整)棵子樹。
例如:這裏是一棵3階B樹,這裏圖中綠色圓角矩形中的每個結點都至少有([m/2]=[3/2]=[1.5]=1.5向上取整=2) 2棵子樹。可以看到,這裏是符合的。
性質3限定的是B樹單個結點的最小規模。(性質1限定的是B樹單個結點的最大規模)
性質4
非葉節點的結構
解析:節點上的指針指向的結點的key與當前結點的key,這些值從左到右是以從小到大的順序排列的。
即:設p1v表示指針1指向的結點的最大的key;k1表示key1的值,則有:p0v<k1<p1v<k2<p2v<…<kn<pnv
如該例子中的:12<15<20<22<…<75<80
性質5
所有的葉子節點都出現在同一層次上,並不帶任何信息
解析:圖中紅色矩形框中的結點均爲葉子節點,看得出它們都在最下層,並不帶任何信息,因此用null表示。
三、常用操作
1.插入
B樹元素的插入
例如給定如下key【 20,30,50,52,60,68,70 】創建一個3階B樹。
(性質1要求子樹數<=3,性質3要求子樹數>=2)
插入20:
Ok,滿足3階B樹的性質,繼續插入
插入30:
Ok,滿足3階B樹的性質,繼續插入
插入50:
NO,3階B樹最多只能有3個子樹,這裏有了4棵子樹,違反了“性質1”;於是開始進行“結點的分裂”(提出中間位置( [3/2]=2 )的key 30,將其作爲獨立節點。
Ok,滿足3階B樹的性質,繼續插入
插入52:
Ok,滿足3階B樹的性質,繼續插入
插入60:
No,不滿足3階B樹的性質1,這裏有了4棵子樹,違反了“性質1”;於是開始進行“結點的分裂”
Ok,滿足3階B樹的性質,繼續插入
插入68:
Ok,滿足3階B樹的性質,繼續插入
插入70:
No,不滿足3階B樹的性質1,這裏有了4棵子樹,違反了“性質1”;於是開始進行“結點的分裂”
No,分裂之後仍然不滿足3階B樹的性質1,這里根節點有了4棵子樹,違反了“性質1”;於是繼續進行“結點的分裂”
Ok,滿足3階B樹的性質,完成插入。
小結:插入操作主要涉及到兩個操作,一是節點的分裂:中間位置( [3/2]=[1.5]=1.5向上取整=2 )key的踢出,使其作爲獨立的結點。結點的合併:被踢出的中間key合併到其父節點,也可以看成是中間key先變成了獨立結點,再與其父結點合併。
2.結點的刪除
刪除的關鍵:要使得刪除後的結點中的key個數>=[m/2]-1,因此將涉及到結點的“合併”問題。可以分爲關鍵字在終端結點上和不在終端結點上兩種情況。
情況的劃分:
1)關鍵字在終端結點上
1.1 結點內key數量>[m/2]-1,刪除key不會破壞其作爲B樹的結構,可以直接刪除。
1.2 結點內key數量=[m/2]-1,並且其左右兄弟結點中存在key數量>[m/2]-1的結點,則去兄弟結點中借key。
註釋:從兄弟結點借key“20”,將它獨立爲一個節點,然後按照規則排列涉及到的節點。
1.3 結點內key數量=[m/2]-1,並且其左右兄弟結點中不存在key數量>[m/2]-1的結點,則需要進行結點合併。
2)關鍵字不在終端結點上
補充定義:
相鄰關鍵字key:對於不在終端結點上的key,它的相鄰key是其左子樹中值最大的key和其右子樹中值最小的key。注意是子樹而不是子節點中。
“20”的相鄰key:“19”和“39”
“52”的相鄰key:“50”和“60”
需要先轉換成在終端結點上,再按照在終端結點上的情況來分別考慮對應的方法。
刪除“52”
第一步:待刪除key與位於終端結點的相鄰key互換位置
第二步:刪除換位之後的待刪除key