Files
Data-Structure/BinaryTree/BalanceTree/B-Tree/B-Tree-By-AI.h
2025-08-26 19:21:23 +08:00

242 lines
8.1 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <iostream>
#include <vector>
using namespace std;
template <class T>
struct Node {
bool leaf; // 是否为叶子节点
vector<T> keys; // 存储关键字
vector<Node*> children; // 孩子节点指针
Node(bool _leaf) : leaf(_leaf) {}
};
template <class T>
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<T>* root;
int t; // 最小度数
// ----------- 插入相关辅助函数 -----------
void insertNonFull(Node<T>* node, const T& key); // 在非满节点插入
void splitChild(Node<T>* parent, int idx); // 分裂子节点
// ----------- 删除相关辅助函数 -----------
void remove(Node<T>* node, const T& key); // 递归删除
void removeFromLeaf(Node<T>* node, int idx); // 从叶子节点删除
void removeFromNonLeaf(Node<T>* node, int idx); // 从非叶子节点删除
T getPredecessor(Node<T>* node, int idx); // 找前驱
T getSuccessor(Node<T>* node, int idx); // 找后继
void fill(Node<T>* node, int idx); // 保证孩子节点至少 t-1 个关键字
void borrowFromPrev(Node<T>* node, int idx); // 从左兄弟借一个关键字
void borrowFromNext(Node<T>* node, int idx); // 从右兄弟借一个关键字
void merge(Node<T>* node, int idx); // 与右兄弟合并
// ----------- 遍历辅助函数 -----------
void traverse(Node<T>* node);
};
// ---------------------- 插入相关 ----------------------
template<class T>
void BTree<T>::insert(const T& key) {
if (!root) { // 树空
root = new Node<T>(true);
root->keys.push_back(key);
} else {
// 根节点满,先分裂根节点
if (root->keys.size() == 2*t - 1) {
Node<T>* s = new Node<T>(false);
s->children.push_back(root);
splitChild(s, 0);
root = s;
}
insertNonFull(root, key); // 插入非满节点
}
}
template<class T>
void BTree<T>::insertNonFull(Node<T>* 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<class T>
void BTree<T>::splitChild(Node<T>* parent, int idx) {
Node<T>* y = parent->children[idx];
Node<T>* z = new Node<T>(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<class T>
void BTree<T>::remove(const T& key) {
if (!root) return;
remove(root, key);
// 如果根节点被删除后没有关键字,调整 root
if (root->keys.empty()) {
Node<T>* oldRoot = root;
if (root->leaf) root = nullptr;
else root = root->children[0];
delete oldRoot;
}
}
template<class T>
void BTree<T>::remove(Node<T>* 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<class T>
void BTree<T>::removeFromLeaf(Node<T>* node, int idx) {
// 叶子节点直接删除关键字
node->keys.erase(node->keys.begin() + idx);
}
template<class T>
void BTree<T>::removeFromNonLeaf(Node<T>* 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<class T>
T BTree<T>::getPredecessor(Node<T>* node, int idx) {
Node<T>* cur = node->children[idx];
while (!cur->leaf) cur = cur->children.back();
return cur->keys.back();
}
template<class T>
T BTree<T>::getSuccessor(Node<T>* node, int idx) {
Node<T>* cur = node->children[idx+1];
while (!cur->leaf) cur = cur->children[0];
return cur->keys[0];
}
template<class T>
void BTree<T>::fill(Node<T>* 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<class T>
void BTree<T>::borrowFromPrev(Node<T>* node, int idx) {
Node<T>* child = node->children[idx];
Node<T>* 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<class T>
void BTree<T>::borrowFromNext(Node<T>* node, int idx) {
Node<T>* child = node->children[idx];
Node<T>* 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<class T>
void BTree<T>::merge(Node<T>* node, int idx) {
Node<T>* child = node->children[idx];
Node<T>* 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<class T>
void BTree<T>::traverse(Node<T>* 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]);
}