1. 程式人生 > >【資料結構】B樹、B+樹與B*樹詳解

【資料結構】B樹、B+樹與B*樹詳解

B樹

1.B樹的定義

  • B樹(B-tree)是對2-3樹資料結構的擴充套件,又稱為多路平衡查詢樹,它的一個節點可以擁有多於2個子節點的二叉查詢樹。與自平衡二叉查詢樹不同,

  • B樹是一種自平衡樹資料結構,可以保持資料排序,它能夠儲存資料、對其進行排序並允許以O(log n)的時間複雜度執行進行查詢、順序讀取、插入和刪除的資料結構

  • B樹針對讀寫大資料塊的系統進行了優化。B樹的演算法減少定位記錄時所經歷的中間過程,從而加快存取速度。普遍運用在資料庫和檔案系統。

注:有人說B-樹,其實就是B樹,因為B樹的原英文名稱為B-tree

2.B樹的性質

一棵m階的B 樹 (m叉樹)的性質

  • 樹中每個結點最多含有m個孩子(m>=2);

  • 若根結點不是葉子結點,則至少有2個孩子

  • 除根結點和葉子結點外,其它每個結點至少有[ceil(m / 2)]個孩子

  • 所有葉子結點都出現在同一層,葉子結點不包含任何關鍵字資訊

  • 每個非終端結點中包含有n個關鍵字資訊,並且以升序排列

B樹實示例圖
這裡寫圖片描述

注:小紅方塊表示這個17檔案內容在硬碟中的儲存位置;p1表示指向17左子樹的指標

3.B樹的插入與刪除

(1)插入的步驟

  • 插入一個元素時,首先在B樹中是否存在,如果不存在,即在葉子結點處結束,然後在葉子結點中插入該新的元素

  • 如果葉子結點空間足夠,這裡需要向右移動該葉子結點中大於新插入關鍵字的元素,如果空間滿了以致沒有足夠的空間去新增新的元素,則將該結點進行“分裂”,將一半數量的關鍵字元素分裂到新的其相鄰右結點中,中間關鍵字元素上移到父結點中(當然,如果父結點空間滿了,也同樣需要“分裂”操作),

  • 當結點中關鍵元素向右移動了,相關的指標也需要向右移。如果在根結點插入新元素,空間滿了,則進行分裂操作,這樣原來的根結點中的中間關鍵字元素向上移動到新的根結點中,因此導致樹的高度增加一層

例項:構造一個包含C N G A H E K Q M F W L T Z D P R X Y S元素的5階B樹
(關鍵字小於2個就合併,超過4個就分裂)

1>結點空間足夠,4個字母插入相同的結點中

這裡寫圖片描述

2>插入H時,結點發現空間不夠,以致將其分裂成2個結點,移動中間元素G上移到新的根結點中,把A和C留在當前結點中,而H和N放置新的其右鄰居結點中

這裡寫圖片描述

3>插入E,K,Q時,不需要任何分裂操作

這裡寫圖片描述

4>插入M需要一次分裂,因為M恰好是中間關鍵字元素,所以向上移到父節點中

這裡寫圖片描述

5>插入F,W,L,T不需要任何分裂操作

這裡寫圖片描述

6>插入Z時,最右的葉子結點空間滿了,需要進行分裂操作,中間元素T上移到父節點中,注意通過上移中間元素,樹最終還是保持平衡,分裂結果的結點存在2個關鍵字元素。

這裡寫圖片描述

7>插入D時,導致最左邊的葉子結點被分裂,D恰好也是中間元素,上移到父節點中,然後字母P,R,X,Y陸續插入不需要任何分裂操作

這裡寫圖片描述

8>最後,當插入S時,含有N,P,Q,R的結點需要分裂,把中間元素Q上移到父節點中,但是情況來了,父節點中空間已經滿了,所以也要進行分裂,將父節點中的中間元素M上移到新形成的根結點中

這裡寫圖片描述

(2)刪除的步驟

  • 首先查詢B樹中需刪除的元素,如果該元素在B樹中存在,則將該元素在其結點中進行刪除,

  • 刪除該元素後,首先判斷該元素是否有左右孩子結點,如果有,則上移孩子結點中的某相近元素(“左孩子最右邊的節點”或“右孩子最左邊的節點”)到父節點中,然後是移動之後的情況;如果沒有,直接刪除後,移動之後的情況。

  • 刪除元素,移動相應元素之後,如果某結點中元素數目(即關鍵字數)小於ceil(m/2)-1,則需要看其某相鄰兄弟結點是否豐滿(結點中元素個數大於ceil(m/2)-1)

  • 如果豐滿,則向父節點借一個元素來滿足條件;如果其相鄰兄弟都剛脫貧,即借了之後其結點數目小於ceil(m/2)-1,則該結點與其相鄰的某一兄弟結點進行“合併”成一個結點,以此來滿足條件。

例項:刪除B樹中的h、r、p、d元素

這裡寫圖片描述

B+樹

1.B+樹的定義

B+-tree是應檔案系統所需而產生的一種B-tree的變形樹。

2.B+樹與B樹區別

  • B+樹中有n棵子樹的結點中含有n個關鍵字,而B 樹是n棵子樹有n-1個關鍵字

  • B+樹所有的葉子結點中包含了全部關鍵字的資訊,及指向含有這些關鍵字記錄的指標,所有的葉子結點和相連的節點使用連結串列按從小到大的順序相連,便於區間查詢和遍歷。而B 樹的葉子節點並沒有包括全部需要查詢的資訊。

  • B+樹所有的非終端結點可以看成是索引部分,結點中僅含有其子樹根結點中最大(或最小)關鍵字。 (而B 樹的非終節點也包含需要查詢的有效資訊)

  • B+樹的葉子結點都是相鏈的,因此對整棵樹的便利只需要一次線性遍歷葉子結點即可。而B樹則需要進行每一層的遞迴遍歷。相鄰的元素可能在記憶體中不相鄰,所以快取命中性沒有B+樹好。

  • B+樹在內部節點上不包含資料資訊,因此在記憶體頁中能夠存放更多的key。 資料存放的更加緊密,具有更好的空間區域性性。因此訪問葉子幾點上關聯的資料也具有更好的快取命中率。B樹的優點:由於B樹的每一個節點都包含key和value,因此經常訪問的元素可能離根節點更近,因此訪問也更迅速。

B+樹示例圖
這裡寫圖片描述

B*樹

1.B*樹的定義

B*-tree是B+-tree的變體,在B+ 樹非根和非葉子結點再增加指向兄弟的指標

2.B*樹的性質

  • B*樹定義了非葉子結點關鍵字個數至少為(2/3)*M,即塊的最低使用率為2/3(代替B+樹的1/2)

  • B+樹的分裂:當一個結點滿時,分配一個新的結點,並將原結點中1/2的資料複製到新結點,最後在父結點中增加新結點的指標;B+樹的分裂隻影響原結點和父結點,而不會影響兄弟結點,所以它不需要指向兄弟的指標。

  • B*樹的分裂:當一個結點滿時,如果它的下一個兄弟結點未滿,那麼將一部分資料移到兄弟結點中,再在原結點插入關鍵字,最後修改父結點中兄弟結點的關鍵字(因為兄弟結點的關鍵字範圍改變了);如果兄弟也滿了,則在原結點與兄弟結點之間增加新結點,並各複製1/3的資料到新結點,最後在父結點增加新結點的指標。

  • B*樹分配新結點的概率比B+樹要低,空間使用率更高;

B*樹示例圖
這裡寫圖片描述

B樹和B+樹的應用場景

1.檔案儲存系統

在B+樹中,內節點只儲存導航用到的key,並不儲存具體值,這樣內節點個數較少,能夠全部讀取到主存中,外接點儲存key及值,並且順序排列,具有良好的空間區域性性。所以B及B+樹比較適合與檔案系統的資料結構。

2.資料庫系統

Mysql的MyISAM和InnoDB兩個儲存引擎的索引實現方式:

  • MyISAM

    • MyISAM引擎使用B+ Tree作為索引結構,葉節點存放的是資料記錄的地址。
    • MyISAM引擎的輔助索引(二級索引)和主索引在結構上沒有區別,只是輔助索引的key可以重複,葉節點上存放的也是資料記錄的地址。
    • MyISAM索引檔案和資料檔案是分離的,索引檔案僅儲存資料記錄的地址。
  • InnoDB

    • InnoDB中表資料本身就是按B+ Tree組織的一個索引結構,葉節點存放的就不是資料記錄的地址,而是完整的資料記錄。所以InnoDB這種儲存方式,又稱為聚集索引,使得按主鍵的搜尋十分高效,但二級索引搜尋需要檢索兩遍索引:首先二級索引獲得主鍵,然後用主鍵到主索引中檢索到資料記錄。
    • 因為主鍵是InnoDB表記錄的”邏輯地址“,所以InnoDB要求表必須有主鍵,MyISAM可以沒有。



本人才疏學淺,若有錯,請指出
謝謝!

參考資料: