1. 程式人生 > >【演算法】B+樹的研讀及實現(1)

【演算法】B+樹的研讀及實現(1)

【前言】

為什麼要明白b+樹?假如大家有操作資料庫及開發有關資料庫的經驗,那麼肯定知道索引這個概念,那麼進一步問你什麼叫索引?

mysql的索引就是B+樹,而其他資料庫我不太清楚,但是,b+樹是一般的索引演算法,當然,oracle、postgres等資料庫聽說也支援r樹的索引方式。

本篇文章先說說b+樹及相應實現方式。

有興趣的話請參閱一下系列文章:

假如大家對b+樹的操作還不是很清楚的話,那麼可以檢視下面這一步操作,不過,假如您已經實現了b樹,那麼b+樹肯定不會難倒您了。

圖解B+樹的插入和刪除(一看就懂)點選開啟


備註:

請注意兩件事,第一:b+樹的非葉子節點不包含任何資料,只包含資料關鍵字的邊界,所以,葉子節點裡面的關鍵字包含非葉子節點的關鍵字,假如碰到非葉子節點擁有葉子節點沒有的關鍵字,請看看這棵樹是不是b+樹;

第二:非葉子節點的第一個關鍵字可以是上邊界,也可以是下邊界,關鍵看你如何處理這個演算法。

現在補充一些b+樹的定義及規則:

(1) 每個節點最多可以有m個元素;

(2) 除了根節點外,每個節點最少有 (m/2) 個元素;


(3) 如果根節點不是葉節點,那麼它最少有2個孩子節點;


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


(5) 一個有k個孩子節點的非葉子節點有 (k-1) 個元素,按升序排列;


(6) 某個元素的左子樹中的元素都比它小,右子樹的元素都大於或等於它;


(7) 非葉子節點只存放關鍵字和指向下一個孩子節點的索引,記錄只存放在葉子節點中;


(8) 相鄰的葉子節點之間用指標相連。


請注意,根節點可以是葉子節點,這種情況出現在什麼地方呢?通常是你剛剛插入關鍵字的時候,只有1到兩個關鍵字,沒有滿足分裂條件,所以剛開始插入資料要考慮這種情況了。

【經過刻苦的程式編寫及除錯,演示程式又完成了,其中最麻煩的部分是拓撲圖的定位及b+樹的插入刪除操作-----bug的程式設計師的命運,這個程式雖然不大,但是各種狀況各種測試也讓人無奈,ok,下面演示一顆b+樹如何插入,如何刪除】

說明:這棵b+樹的階為3,則最多三個關鍵字,最多三個子樹,最少2個關鍵字,最少兩個子樹。

【插入操作演示】

【分別插入關鍵字 10、20、30,此時根節點為葉節點,同時沒有滿足分裂條件,故放到同一個葉節點裡面】


【插入關鍵字7,這時候根節點的關鍵字數量大於m(m=3),所以需要分裂成為兩個子節點(葉節點)】


【分別插入關鍵字8、25,葉子節點被填滿,沒有符合分裂條件,不需要分裂。】


【插入關鍵字6,注意,6是少於所有關鍵字的,根據我的演算法,6將放到最左邊的葉子節點裡面,並且遞迴設定每一個父親的第一位數目(則該路徑上第一個關鍵字都改6),同時,葉子節點關鍵字大於m(m=3),需要分裂,具體演算法可以檢視我的下一篇博文的具體程式碼,裡面已經包含解釋】


【分別插入關鍵字 7.5、12】


【插入關鍵字13,葉子節點滿足分裂條件,分裂以後遞迴調整b+樹的形狀】


【插入關鍵字6.5,滿足分裂條件,分裂之。】


【下面進行刪除操作演示】

【刪除關鍵字12.0,刪除後葉子節點關鍵字數量少於min(min=2),通過檢查可知,右側兄弟有多餘的關鍵字,從右側兄弟那裡借一個關鍵字,具體演算法可以參看我下一篇博文的程式碼,裡面有註釋。】


【刪除關鍵字13.0,刪除後關鍵字數量少於min,並且左右兄弟都沒有多餘的關鍵字,所以只能夠合併葉子節點,合併後需要遞迴進行樹形結構調整,具體演算法參看下一篇博文。】


【刪除關鍵字7.5,刪除後滿足合併條件,進行合併並遞迴調整樹形。】


【刪除關鍵字6.0,刪除關鍵字6.0後,關鍵字數量==min,符合樹形結構,但是父節點的關鍵字代表的是界限,就本演算法而言,父親節點的關鍵字要大於或等於它對應子節點或葉子節點的所有關鍵字,所以,這裡必須進行父親節點下界關鍵字的調整,必要時(當最左邊葉子節點的第一個關鍵字改變了的情況下)甚至需要將同一路徑的所有第一個關鍵字都改變,具體演算法參看下一篇博文。】


【刪除關鍵字8.0,刪除後需要向右邊兄弟借一個關鍵字。】


【刪除關鍵字10.0,需要合併。】


好了,想必大家對b+樹的新增及刪除操作有所認識了,下面我將演示用程式放出來,