數據結構與算法筆記目錄:《戀上數據結構》 筆記目錄
想加深 Java 基礎推薦看這個: Java 強化筆記目錄
B樹是一種平衡的多路搜索樹,多用於文件系統、數據庫的實現;
仔細觀察B樹,有什麼眼前一亮的特點?
- 1 個節點可以存儲超過 2 個元素、可以擁有超過 2 個子節點
- 擁有二叉搜索樹的一些性質
- 平衡,每個節點的所有子樹高度一致
- 比較矮
m階B樹的性質
數據庫實現中一般用幾階B樹?
- 200 ~ 300
B樹 vs 二叉搜索樹
B樹 和 二叉搜索樹,在邏輯上是等價的;
多代節點合併,可以獲得一個超級節點
- 2 代合併的超級節點,最多擁有 4 個子節點(至少是 4 階B樹)
- 3 代合併的超級節點,最多擁有 8 個子節點(至少是 8 階B樹)
- n 代合併的超級節點,最多擁有 2n 個子節點( 至少是 2n 階B樹)
m 階 B樹,最多需要 log2m 代合併;
搜索
跟二叉搜索樹的搜索類似:
- 先在節點內部從小到大開始搜索元素
- 如果命中,搜索結束
- 如果未命中,再去對應的子節點中搜索元素,重複步驟 1
添加 – 上溢
新添加的元素必定是添加到葉子節點:
插入 55:
插入 95:
再插入 98 呢?(假設這是一棵 4階B樹)
- 最右下角的葉子節點的元素個數將超過限制
- 這種現象可以稱之爲:上溢(overflow)
添加 – 上溢的解決(假設5階)
上溢節點的元素個數必然等於 m;
假設上溢節點最中間元素的位置爲 k
- 將 k 位置的元素向上與父節點合併
- 將 [0, k - 1] 和 [k + 1, m - 1] 位置的元素分裂成 2 個子節點
這 2 個子節點的元素個數,必然都不會低於最低限制(┌ m/2 ┐ − 1)
一次分裂完畢後,有可能導致父節點上溢,依然按照上述方法解決
- 最極端的情況,有可能一直分裂到根節點
添加示例:
插入 98:
插入 52:
插入 54:
刪除
刪除 – 葉子節點
假如需要刪除的元素在葉子節點中,那麼直接刪除即可;
例:刪除 30
刪除 – 非葉子節點
假如需要刪除的元素在非葉子節點中
- 先找到前驅或後繼元素,覆蓋所需刪除元素的值
- 再把前驅或後繼元素刪除
例:刪除 60
非葉子節點的前驅或後繼元素,必定在葉子節點中;
- 所以這裏的刪除前驅或後繼元素 ,就是最開始提到的情況:刪除的元素在葉子節點中
- 真正的刪除元素都是發生在葉子節點中;
刪除 – 下溢
刪除 22?(假設這是一棵 5階B樹)
- 葉子節點被刪掉一個元素後,元素個數可能會低於最低限制(
≥
┌ m/2 ┐ − 1 ) - 這種現象稱爲:下溢(underflow)
刪除 – 下溢的解決
下溢節點的元素數量必然等於 ┌ m/2 ┐ − 2
如果下溢節點臨近的兄弟節點,有至少 ┌ m/2 ┐ 個元素,可以向其借一個元素
- 將父節點的元素 b 插入到下溢節點的 0 位置(最小位置)
- 用兄弟節點的元素 a(最大的元素)替代父節點的元素 b
- 這種操作其實就是:旋轉
如果下溢節點臨近的兄弟節點,只有 ┌ m/2 ┐ − 1 個元素
- 將父節點的元素 b 挪下來跟左右子節點進行合併
- 合併後的節點元素個數等於┌ m/2 ┐ + ┌ m/2 ┐ − 2,不超過 m − 1
- 這個操作可能會導致父節點下溢,依然按照上述方法解決,下溢現象可能會一直往上傳播
刪除示例:
4階B樹
如果先學習 4 階 B 樹(2 - 3 - 4 樹),將能更好地學習理解紅黑樹:
4階B樹的性質:
- 所有節點能存儲的元素個數 x :1 ≤ x ≤ 3
- 所有非葉子節點的子節點個數 y :2 ≤ y ≤ 4
添加:從 1 添加到 22