B樹是數據庫索引的核心數據結構,本文提供一個基於 C++ 模板的完整 B樹實現,包含插入、刪除、分裂、合併等核心操作,並詳細解析關鍵邏輯。
2m-1 = 5 個關鍵字m-1 = 2 個關鍵字template <class T>
class BTnode {
friend class BTree<T>;
bool isleaf; // 是否葉子
int keyNum; // 關鍵字數量
BTnode* parent; // 父節點
BTnode* pchild[6]; // 子節點指針數組 (child_max = 6)
T keyvalue[5]; // 關鍵字數組 (key_max = 5)
};
template <class T>
class BTree {
BTnode<T>* root;
// 核心操作:插入、分裂、刪除、合併、查找、打印
};
Notfull_insert 向非滿節點插入SplitBlock將滿節點 node_child 分裂為左右兩個節點,中間關鍵字上移到父節點 node_parent 的 child_index 位置:
void SplitBlock(BTnode<T>* parent, int idx, BTnode<T>* child) {
BTnode<T>* right = new BTnode<T>();
right->isleaf = child->isleaf;
right->keyNum = key_min; // 2
// 複製右半部關鍵字
for (int i = 0; i < key_min; ++i)
right->keyvalue[i] = child->keyvalue[i + child_min];
// 非葉子需複製子指針並更新父指針
if (!child->isleaf) {
for (int i = 0; i < child_min; ++i) {
right->pchild[i] = child->pchild[i + child_min];
right->pchild[i]->parent = right;
}
}
child->keyNum = key_min;
// 父節點騰出位置,上移中間關鍵字
for (int i = parent->keyNum; i > idx; --i) {
parent->keyvalue[i] = parent->keyvalue[i-1];
parent->pchild[i+1] = parent->pchild[i];
}
parent->keyvalue[idx] = child->keyvalue[key_min];
parent->pchild[idx+1] = right;
right->parent = parent;
parent->keyNum++;
}
刪除分兩階段:
BTree_delete 處理根節點特殊情況(根只有一個關鍵字且孩子也剛好滿足最小度)BTree_deletebalance 遞歸刪除並修復不平衡修復策略(由易到難):
T getprev(BTnode<T>* node) { // 左子樹最大值
while (!node->isleaf) node = node->pchild[node->keyNum];
return node->keyvalue[--node->keyNum];
}
T getnext(BTnode<T>* node) { // 右子樹最小值
while (!node->isleaf) node = node->pchild[0];
return node->keyvalue[0];
}
代碼包含以下核心函數:
| 函數 | 功能 |
|---|---|
BTree_insert | 插入入口,處理根分裂 |
Notfull_insert | 向非滿節點遞歸插入 |
SplitBlock | 節點分裂 |
BTree_delete | 刪除入口,處理根特殊情況 |
BTree_deletebalance | 遞歸刪除並平衡 |
MergeBlock | 合併兩個兄弟節點 |
getprev/getnext | 查找前驅/後繼關鍵字 |
BTree_find | 查找關鍵字 |
printpoint | 樹狀打印結構 |
BTree<int> tree; tree.BTree_insert(10); tree.BTree_insert(20); tree.BTree_insert(5); tree.printpoint(); // 可視化輸出樹結構