#include #include using namespace std; template struct Node { bool leaf; // 是否为叶子节点 vector keys; // 存储关键字 vector children; // 孩子节点指针 Node(bool _leaf) : leaf(_leaf) {} }; template class BTree { public: BTree(int _t) : t(_t), root(nullptr) {} void insert(const T& key); // 插入关键字 void remove(const T& key); // 删除关键字 void traverse() { traverse(root); cout << endl; } // 中序遍历 private: Node* root; int t; // 最小度数 // ----------- 插入相关辅助函数 ----------- void insertNonFull(Node* node, const T& key); // 在非满节点插入 void splitChild(Node* parent, int idx); // 分裂子节点 // ----------- 删除相关辅助函数 ----------- void remove(Node* node, const T& key); // 递归删除 void removeFromLeaf(Node* node, int idx); // 从叶子节点删除 void removeFromNonLeaf(Node* node, int idx); // 从非叶子节点删除 T getPredecessor(Node* node, int idx); // 找前驱 T getSuccessor(Node* node, int idx); // 找后继 void fill(Node* node, int idx); // 保证孩子节点至少 t-1 个关键字 void borrowFromPrev(Node* node, int idx); // 从左兄弟借一个关键字 void borrowFromNext(Node* node, int idx); // 从右兄弟借一个关键字 void merge(Node* node, int idx); // 与右兄弟合并 // ----------- 遍历辅助函数 ----------- void traverse(Node* node); }; // ---------------------- 插入相关 ---------------------- template void BTree::insert(const T& key) { if (!root) { // 树空 root = new Node(true); root->keys.push_back(key); } else { // 根节点满,先分裂根节点 if (root->keys.size() == 2*t - 1) { Node* s = new Node(false); s->children.push_back(root); splitChild(s, 0); root = s; } insertNonFull(root, key); // 插入非满节点 } } template void BTree::insertNonFull(Node* node, const T& key) { int i = node->keys.size() - 1; if (node->leaf) { // 叶子节点直接插入 node->keys.push_back(key); while (i >= 0 && node->keys[i] > key) { node->keys[i+1] = node->keys[i]; i--; } node->keys[i+1] = key; } else { // 内部节点 while (i >= 0 && node->keys[i] > key) i--; i++; if (node->children[i]->keys.size() == 2*t-1) { splitChild(node, i); // 分裂满子节点 if (node->keys[i] < key) i++; } insertNonFull(node->children[i], key); } } template void BTree::splitChild(Node* parent, int idx) { Node* y = parent->children[idx]; Node* z = new Node(y->leaf); // 把 y 的后 t-1 个关键字移动到 z for (int j = 0; j < t-1; j++) z->keys.push_back(y->keys[j+t]); if (!y->leaf) { for (int j = 0; j < t; j++) z->children.push_back(y->children[j+t]); y->children.resize(t); } y->keys.resize(t-1); // 保留前 t-1 个关键字 parent->children.insert(parent->children.begin()+idx+1, z); parent->keys.insert(parent->keys.begin()+idx, y->keys[t-1]); // 中间关键字上移 } // ---------------------- 删除相关 ---------------------- template void BTree::remove(const T& key) { if (!root) return; remove(root, key); // 如果根节点被删除后没有关键字,调整 root if (root->keys.empty()) { Node* oldRoot = root; if (root->leaf) root = nullptr; else root = root->children[0]; delete oldRoot; } } template void BTree::remove(Node* node, const T& key) { int idx = 0; while (idx < node->keys.size() && node->keys[idx] < key) idx++; if (idx < node->keys.size() && node->keys[idx] == key) { if (node->leaf) removeFromLeaf(node, idx); // 情况1: 叶子节点直接删除 else removeFromNonLeaf(node, idx); // 情况2: 内部节点 } else { if (node->leaf) return; // key不存在 bool flag = (idx == node->keys.size()); // 如果孩子节点关键字不足 t 个,需要调整 if (node->children[idx]->keys.size() < t) fill(node, idx); if (flag && idx > node->keys.size()) remove(node->children[idx-1], key); else remove(node->children[idx], key); } } template void BTree::removeFromLeaf(Node* node, int idx) { // 叶子节点直接删除关键字 node->keys.erase(node->keys.begin() + idx); } template void BTree::removeFromNonLeaf(Node* node, int idx) { T k = node->keys[idx]; // 如果左孩子关键字 >= t,用前驱替换 if (node->children[idx]->keys.size() >= t) { T pred = getPredecessor(node, idx); node->keys[idx] = pred; remove(node->children[idx], pred); } // 如果右孩子关键字 >= t,用后继替换 else if (node->children[idx+1]->keys.size() >= t) { T succ = getSuccessor(node, idx); node->keys[idx] = succ; remove(node->children[idx+1], succ); } // 左右孩子都不足 t,则合并孩子 else { merge(node, idx); remove(node->children[idx], k); } } template T BTree::getPredecessor(Node* node, int idx) { Node* cur = node->children[idx]; while (!cur->leaf) cur = cur->children.back(); return cur->keys.back(); } template T BTree::getSuccessor(Node* node, int idx) { Node* cur = node->children[idx+1]; while (!cur->leaf) cur = cur->children[0]; return cur->keys[0]; } template void BTree::fill(Node* node, int idx) { // 尝试从兄弟借关键字,如果不够则合并 if (idx != 0 && node->children[idx-1]->keys.size() >= t) borrowFromPrev(node, idx); else if (idx != node->keys.size() && node->children[idx+1]->keys.size() >= t) borrowFromNext(node, idx); else { if (idx != node->keys.size()) merge(node, idx); else merge(node, idx-1); } } template void BTree::borrowFromPrev(Node* node, int idx) { Node* child = node->children[idx]; Node* sibling = node->children[idx-1]; // 将父节点关键字下移到 child 前面 child->keys.insert(child->keys.begin(), node->keys[idx-1]); if (!child->leaf) child->children.insert(child->children.begin(), sibling->children.back()); node->keys[idx-1] = sibling->keys.back(); sibling->keys.pop_back(); if (!sibling->leaf) sibling->children.pop_back(); } template void BTree::borrowFromNext(Node* node, int idx) { Node* child = node->children[idx]; Node* sibling = node->children[idx+1]; // 将父节点关键字下移到 child 后面 child->keys.push_back(node->keys[idx]); if (!child->leaf) child->children.push_back(sibling->children[0]); node->keys[idx] = sibling->keys[0]; sibling->keys.erase(sibling->keys.begin()); if (!sibling->leaf) sibling->children.erase(sibling->children.begin()); } template void BTree::merge(Node* node, int idx) { Node* child = node->children[idx]; Node* sibling = node->children[idx+1]; // 将父节点关键字和 sibling 的关键字都移入 child child->keys.push_back(node->keys[idx]); child->keys.insert(child->keys.end(), sibling->keys.begin(), sibling->keys.end()); if (!child->leaf) child->children.insert(child->children.end(), sibling->children.begin(), sibling->children.end()); // 删除父节点中的关键字和 sibling 指针 node->keys.erase(node->keys.begin() + idx); node->children.erase(node->children.begin() + idx + 1); delete sibling; } // ---------------------- 遍历 ---------------------- template void BTree::traverse(Node* node) { if (!node) return; int i; for (i = 0; i < node->keys.size(); i++) { if (!node->leaf) traverse(node->children[i]); cout << node->keys[i] << " "; } if (!node->leaf) traverse(node->children[i]); }