徹底搞定篇–B+Tree(1)

  • 2019 年 10 月 5 日
  • 筆記

對話

老王:最近怎麼沒精打採的呢?

小王:最近面試卡住了,B+ tree 沒回答上來

老王:不對呀,你不早就學過嗎,經典教程都寫這呢?

小王:別提啦,當時腦中一片空白。

當時情況是這樣的!


大王:談談你對B+ tree理解?

小王:這個我知道,就是數據全部存儲到葉子節點上,在同一層次 !

大王;然後呢。。。。

小王:支支吾吾 說不上來了。

大王:還有沒有補充的

小王:查詢效率很高。

大王:怎麼查詢的?

小王:。。。。。。。

大王:過,就到這裡。

老王:我來講一講

(老王) 我演示一下如何查找

  • 查找元素6
  • 查找元素12
  • 查找元素17 (慢速)

(小王)我知道如何查找了

查詢tree_search (k, root) 邏輯

  1. 如果root為null,直接返回查詢失敗。
  2. 如果是root是葉子節點,if k=ki,返回查找成功,不然就失敗。
  3. root 如果是非葉子節點。 循環遍歷 如果 k <key1

從對應子樹 繼續尋找tree_search (k, root.1.child) 遞歸遍歷

  1. 循環遍歷結束。k 大於任何一個key。指針多一個 tree_search (k, root.last.child) 偽程式碼
Function: tree_search (k, node)    if node is a leaf then      return node;    switch k do    case k ≤ k_0      return tree_search(k, p_0);    case k_i < k ≤ k_{i+1}      return tree_search(k, p_{i+1});    case k_d < k      return tree_search(k, p_{d});  

小王:

我有一個疑問,查詢元素12時候,明明中間元素 已經存在,為什麼還要繼續查詢走到葉子節點才算結束, 這不是浪費時間嗎?

老王:

觀察很仔細呀,漫畫演算法:什麼是 B+ 樹。

程式設計師小灰已經給出解釋了,你不是看過一次,怎麼忘記了!

小王:

我確實看過,不過對裡面一句話根本不明白

有K個元素,K個指針 ,一個節點對應一個指針呀, 這個不對呀,2個元素會拆分3個指針呢?

(老王) 先別急著問為什麼,我演示一下插入操作

在葉子節點 (1 2 3) 上插入新元素 4 ,B tree 結果是

在葉子節點 (1 2 3) 上插入新元素 4 ,B+ tree 結果是

順序插入元素:1 2 3 4 5 6 7 9 10 11 創建 4 階 B+ tree 完整演示(慢速10倍)

(小王)我知道如何插入了

插入關鍵字k的步驟

  1. 選擇到葉子節點,然後插入對應位置
  2. 對葉子節點做平衡檢查,如果超過上界,選擇中間元素+1位置這個key進行拆分到paernt節點上去。
  3. 繼續對父節點做做平衡檢查。如果超過上界,選擇中間元素+1位置這個key進行拆分到paernt節點上去
  4. 重複步驟 3

(老王)請看下面刪除演示

刪除元素 5

刪除元素 7

7.gif

(小王)這個有點複雜,需要藉助相鄰的元素,這個操作我描述不出來

基本分為三個步驟

  1. 從葉子節點查詢到該元素,然後刪除
  2. 判斷是是否低於最低數量,從該節點借一個記錄代替自己。如果沒有從鄰居借去一個代替自己
  3. 重複步驟 2

但是漏洞很多,無法具體描述。開始支支吾吾了

(老王) 你說對,這個情況比較複雜。未完待續

最後,小王偷偷寫下這麼幾句話

B+ tree 是一個 M 階平衡搜索樹 (Balanced multiway search trees)

  1. 為了維持平衡,每個非葉子節點中子樹個數上下界:M/2<=x <<M。也就是說 每個結點最多有m-1個關鍵字
  2. 每次對葉子節點 中key的 插入,刪除等操作會引起關鍵字超過上下界,因此需要繼續進行拆分或者合併操作。
  3. 因為全部資訊都存儲到葉子節點,這就為什麼每次查詢,插入,刪除等操從找到葉子節點開始。

哈哈哈

你一已經猜到 一個4階B+tree,一個節點最多允許 3個key,4個子樹指針。

因為B+ tree 結構是遞歸的,我只專心看最小子問題,就是一個節點組成

typedef struct BTNode{          int keynum;       /// 結點中關鍵字的個數,ceil(ORDER/2)-1<= keynum <= ORDER-1          KeyType key[ORDER-1];         /// 關鍵字向量為key[0..keynum - 1]          struct BTNode* child[ORDER];   /// 孩子指針向量為child[0..keynum]          char isLeaf;         /// 是否是葉子節點的標誌      }BTNode;  

數據結構和演算法結構化

FQA

  • 一個M階的B+tree,M是什麼意思,是節點個數,還是指針個數?目前我定義來看是孩子的最大個數?
  • 每個節點 n個key和m個指針 ,n和m一定相等嗎?不一定

參考

B+ treeFrom Wikipedia

MySQL索引背後的數據結構及演算法原理

漫畫演算法:什麼是 B+ 樹

演算法導論 18章