1. 程式人生 > 其它 >B樹平衡過程-根節點為什麼最少要有兩個子節點?

B樹平衡過程-根節點為什麼最少要有兩個子節點?

技術標籤:MySQL資料結構

一顆m階的B樹,這裡階的意思是指每個節點擁有的子節點個數,會滿足以下幾點:

1)每個節點最多有m個子節點

(2)除了根節點和葉子節點之外,其它的每個節點最少有m/2(向上取整)個子節點

(3)根節點至少有兩個子節點,(除了第一次插入的時候,此時只有一個節點,根節點同時是葉子節點)

(4)所有的葉子節點都在同一層

(5)有k個子節點的父節點包含k-1個key關鍵字

初次接觸B樹的時候有兩個問題比較疑惑,根節點為什麼最少要有兩個子節點?其它的節點為什麼又是最少有m/2個子節點?直到看到這篇部落格之後茅塞頓開。簡單來講B樹的上述幾個條件就是為了維持樹的平衡。

下面舉個例子來說明一下,所有的圖片都是來自於Data Structure Visualization網站,可以保證圖片的正確性。
我們依次往一顆B樹裡邊插入遞增的數字來觀察樹形狀的變化。
第一個例子,m=3,一顆三階的B樹,依次插入1,2,3。

1,2
當3這個key插入的時候,首先試圖插入根節點,但是此時根節點總共有4個子節點(下圖4個指向子節點的childPtr),不滿足條件1,即子節點數量不能超過3,於是根節點要分裂。

在這裡插入圖片描述
在這裡插入圖片描述

根節點一分為三,分裂之後是這樣的:
在這裡插入圖片描述
分裂的時候,中間的以中間的key-2為中心,將keys分成三份,中間的key作為新的根節點;左邊的部分作為新根節點的左子樹,同樣的道理右邊的部分作為右子樹。

也就是說中間的key成為根節點後,至少兩個子節點,這就是條件3,這就是根節點為什麼至少兩個子節點的原因。
我們繼續往b樹新增key。
在這裡插入圖片描述
當5加進去的時候,最右邊葉子節點不滿足條件,分裂。
在這裡插入圖片描述

在這裡插入圖片描述

加入6
在這裡插入圖片描述
當7進去的時候,會導致最右邊的葉子節點不滿足要求,於是葉子節點右開始分裂
在這裡插入圖片描述
當key(6)上移到它的父節點之後又會導致父節點不滿足要求,繼續分裂。
在這裡插入圖片描述
最後的b樹如下,此時樹的高度變為了3.
在這裡插入圖片描述
可以這麼理解,隨著資料的不斷加入,樹的高度就會慢慢變高,b樹的層數增加是通過分裂根節點完成的。
當根節點要分裂的時候,為什麼是分裂成左右兩個子樹而不能分裂成超過兩個子樹呢?這是由於條件2:除了根節點和葉子節點之外,其它的每個節點最少有m/2(向上取整)個子節點。如果分成三個子節點,那麼每個子節點的包含的節點數就是m/3,不滿足條件2。

再舉一個例子
下面再建個7階的b樹,依次加入1,2,3,4,5,6,7。
在這裡插入圖片描述
當7加入的時候,根節點共有8個child指標,不滿足條件1,所以要分裂,這種情況就以中間的key(4)作為新的根節點,1,2,3作為新的根節點的左子節點,5,6,7作為右子節點。變成這個樣子:
在這裡插入圖片描述
第三個例子,這個例子其實重複了,只是多舉點例子加深理解
下圖是根節點第二次分裂的情況,這是一顆5階b樹,儲存1到16的key,目前高度為2
在這裡插入圖片描述
當我們往這顆b樹加入17的時候,最右邊的葉子有6個childPtr,不滿足條件1。所以這個節點也要執行分裂,的中間的key(15)要上移到父節點,同時分裂為兩個節點,此時它的父節點就是根節點。但是分裂之後就會導致根節點不滿足要求,此時根節點有6個子節點。
在這裡插入圖片描述
由於根節點不滿足要求,所以根節點也要執行分裂操作。
在這裡插入圖片描述
還是以中間的key作為新的根節點,左右兩邊分別作為左右子樹,變成這個樣子:
在這裡插入圖片描述
這時候新的根節點還是兩個子樹,通過上面的幾個例子很容易理解根節點為什麼最少要有兩個子節點