看圖輕鬆理解資料結構與演算法系列(B樹)

超人汪小建發表於2018-08-30

前言

推出一個新系列,《看圖輕鬆理解資料結構和演算法》,主要使用圖片來描述常見的資料結構和演算法,輕鬆閱讀並理解掌握。本系列包括各種堆、各種佇列、各種列表、各種樹、各種圖、各種排序等等幾十篇的樣子。

B樹

B樹即平衡查詢樹,一般理解為平衡多路查詢樹,也稱為B-樹、B_樹。是一種自平衡樹狀資料結構,能對儲存的資料進行O(log n)的時間複雜度進行查詢、插入和刪除。B樹一般較多用在儲存系統上,比如資料庫或檔案系統。

B樹特點

  • B樹可以定義一個m值作為預定範圍,即m路(階)B樹。
  • 每個節點最多有m個孩子。
  • 每個節點至少有ceil(m/2)個孩子,除了根節點和葉子節點外。
  • 對於根節點,子樹個數範圍為[2,m],節點內值的個數範圍為[1,m-1]。
  • 對於非根節點,節點內的值個數範圍為[ceil(m/2)-1,m-1]。
  • 根節點(非葉子節點)至少有兩個孩子。
  • 一個有k個孩子的非葉子節點包含k-1個值。
  • 所有葉子節點在同一層。
  • 節點內的值按照從小到大排列。
  • 父節點的若干值作為分離值分成多個子樹,左子樹小於對應分離值,對應分離值小於右子樹。

以下是一個四階B樹,

image

插入

假設現在構建一棵四階B樹,開始插入“A”,直接作為根節點,

image

插入“B”,大於“A”,放右邊,

image

插入“C”,按順序排到最後,

image

繼續插入“D”,直接新增的結果如下圖,此時超過了節點可以存放容量,對於四階B樹每個節點最多存放3個值,此時需要執行分裂操作,

image

分裂操作為,先選取待分裂節點的中值,這裡為“B”,然後將中值“B”放到父節點中,因為這裡還沒有父節點,那麼直接建立一個新的父節點存放“B”,而原來小於“B”的那些值作為左子樹,原來大於“B”的那些值作為右子樹。

image

繼續插入“E”,"E"大於“B”,往右子節點,

image

分別於“C”和“D”比較,大於它們,放到最右邊,

image

插入“F”,“F”大於“B”,往右子樹,

image

“F”分別與“C”"D""E"比較,大於它們,放到最右邊,此時觸發分裂操作,

image

選取待分裂節點的中值“D”,然後將中值“D”放到父節點中,父節點中的“B”小於“D”,於是放到“B”右邊,而原來小於“D”的那些值作為左子樹,原來大於“D”的那些值作為右子樹。

image

繼續插入“M”,結果為,

image

插入“L’,大於“B”“D”,往右子樹,

image

“L”大於“E”“F”小於“M”,於是放到第三個位置,此時觸發分裂操作,

image

選取待分裂節點的中值“F”,然後將中值“F”放到父節點中,父節點中的“B”“D”都小於“F”,於是放到最右邊,而原來小於“F”的那些值作為左子樹,原來大於“F”的那些值作為右子樹。

image

插入“K”,結果為,

image

插入“J”,大於“B”“D”“F”,往右子樹,

image

“J”小於“K”“L”“M”,於是放到第一個位置,此時觸發分裂操作,

image

選取待分裂節點的中值“K”,然後將中值“K”放到父節點中,父節點中的“B”“D”“F”都小於“K”,於是放到最右邊,而原來小於“K”的那些值作為左子樹,原來大於“K”的那些值作為右子樹。此時父節點也觸發分裂操作,

image

選取待分裂節點的中值“D”,然後將中值“D”放到父節點中,由於還沒有父節點,那麼直接建立一個新的父節點存放“D”,而原來小於“D”的那些值作為左子樹,原來大於“D”的那些值作為右子樹。

image

插入“I”,大於“D”,往右子樹,

image

右子樹不是葉子節點,繼續往下,這時“I”大於“F”而小於“K”,所以往第二個分支,

image

“I”小於“J”,於是放到左邊,

image

類似地,插入“H”,結果如下,

image

插入“G”,往左子樹,

image

往中間分支,

image

觸發分裂操作,

image

選取待分裂節點的中值“H”,然後將中值“H”放到父節點中,"H"大於父節點中的“F”而小於“K”,於是放到中間,而原來小於“H”的那些值作為左子樹,原來大於“H”的那些值作為右子樹。

image

綜上所述,插入操作的核心是分裂操作。無需分裂的情況比較簡單,直接插入即可;如果插入後超過節點容量,這個容量可預先自定義,則需要進行分裂操作,需要注意的是分裂可能引起父節點需要繼續分裂。

查詢

對B樹進行查詢就比較簡單,查詢過程有點類似二叉搜尋樹,從根節點開始查詢,根據比較數值找到對應的分支,繼續往子樹上查詢。

比如查詢“I”,"I"大於“D”,往右子樹,

image

“I”分別與節點內值比較,大於“F”“H”而小於“K”,往第三個分支,

image

逐一比較節點內的值,找到“I”。

image

-------------推薦閱讀------------

我的開源專案彙總(機器&深度學習、NLP、網路IO、AIML、mysql協議、chatbot)

為什麼寫《Tomcat核心設計剖析》

我的2017文章彙總——機器學習篇

我的2017文章彙總——Java及中介軟體

我的2017文章彙總——深度學習篇

我的2017文章彙總——JDK原始碼篇

我的2017文章彙總——自然語言處理篇

我的2017文章彙總——Java併發篇


跟我交流,向我提問:

看圖輕鬆理解資料結構與演算法系列(B樹)

歡迎關注:

看圖輕鬆理解資料結構與演算法系列(B樹)

相關文章