以下是带有分裂和合并操作的B+树实现,包括了分裂和合并节点的过程:
#include <iostream>
#include <vector>
#include <algorithm>
// B+树节点
template<typename KeyType, typename ValueType>
class BPlusTreeNode {
public:
bool leaf; // 是否为叶子节点
std::vector<KeyType> keys; // 键值列表
std::vector<ValueType> values; // 值列表
BPlusTreeNode<KeyType, ValueType>* parent; // 父节点
std::vector<BPlusTreeNode<KeyType, ValueType>*> children; // 子节点列表
// 构造函数
BPlusTreeNode(bool _leaf) : leaf(_leaf), parent(nullptr) {}
// 在节点中查找键值
int findKey(const KeyType& key) {
auto it = std::lower_bound(keys.begin(), keys.end(), key);
return std::distance(keys.begin(), it);
}
// 插入键值
void insert(const KeyType& key, const ValueType& value) {
auto it = std::lower_bound(keys.begin(), keys.end(), key);
int idx = std::distance(keys.begin(), it);
keys.insert(it, key);
values.insert(values.begin() + idx, value);
}
// 分裂节点
void split(BPlusTreeNode<KeyType, ValueType>*& newParent) {
// 创建新的右节点
BPlusTreeNode<KeyType, ValueType>* rightNode = new BPlusTreeNode<KeyType, ValueType>(leaf);
int midIdx = keys.size() / 2;
rightNode->keys.assign(keys.begin() + midIdx, keys.end());
rightNode->values.assign(values.begin() + midIdx, values.end());
if (!leaf) {
rightNode->children.assign(children.begin() + midIdx, children.end());
for (auto& child : rightNode->children) {
child->parent = rightNode;
}
children.erase(children.begin() + midIdx, children.end());
}
keys.resize(midIdx);
values.resize(midIdx);
// 插入新节点到父节点中
int insertIdx = parent->findKey(keys[0]);
parent->insert(keys[midIdx], values[midIdx]);
parent->children.insert(parent->children.begin() + insertIdx + 1, rightNode);
rightNode->parent = parent;
// 如果父节点的键值个数超过阈值,则继续分裂父节点
if (parent->keys.size() > maxKeys) {
parent->split(newParent);
} else {
newParent = parent;
}
}
// 合并节点
void merge(BPlusTreeNode<KeyType, ValueType>*& newParent) {
// 找到当前节点在父节点中的位置
int parentIdx = parent->findKey(keys[0]);
BPlusTreeNode<KeyType, ValueType>* sibling = nullptr;
// 如果当前节点不是父节点的第一个子节点,那么合并它和左兄弟
if (parentIdx > 0) {
sibling = parent->children[parentIdx - 1];
}
// 否则合并它和右兄弟
else {
sibling = parent->children[parentIdx + 1];
}
// 将父节点的键值和子节点合并到当前节点
keys.push_back(parent->keys[parentIdx]);
keys.insert(keys.end(), sibling->keys.begin(), sibling->keys.end());
values.insert(values.end(), sibling->values.begin(), sibling->values.end());
children.insert(children.end(), sibling->children.begin(), sibling->children.end());
// 删除父节点的键值和子节点
parent->keys.erase(parent->keys.begin() + parentIdx);
parent->children.erase(parent->children.begin() + parentIdx + 1);
// 如果父节点的键值个数小于最小键值个数,继续合并父节点
if (parent->keys.size() < minKeys) {
parent->merge(newParent);
} else {
newParent = parent;
}
}
private:
static constexpr int maxKeys = 3; // 节点的最大键值个数
static constexpr int minKeys = maxKeys / 2; // 节点的最小键值个数
};
// B+树
template<typename KeyType, typename ValueType>
class BPlusTree {
public:
BPlusTree() : root(nullptr) {}
// 查找键值
bool search(const KeyType& key) {
return root ? root->search(key) : false;
}
// 插入键值
void insert(const KeyType& key, const ValueType& value) {
if (!root) {
root = new BPlusTreeNode<KeyType, ValueType>(true);
root->insert(key, value);
} else {
BPlusTreeNode<KeyType, ValueType>* node = findLeafNode(key);
node->insert(key, value);
if (node->keys.size() > node->maxKeys) {
BPlusTreeNode<KeyType, ValueType>* newParent = nullptr;
node->split(newParent);
if (newParent) {
root = newParent;
}
}
}
}
private:
BPlusTreeNode<KeyType, ValueType>* root;
// 查找叶子节点
BPlusTreeNode<KeyType, ValueType>* findLeafNode(const KeyType& key) {
BPlusTreeNode<KeyType, ValueType>* curr = root;
while (!curr->leaf) {
int idx = curr->findKey(key);
curr = curr->children[idx];
}
return curr;
}
};
int main() {
BPlusTree<int, std::string> tree;
tree.insert(10, "Value 1");
tree.insert(20, "Value 2");
tree.insert(5, "Value 3");
tree.insert(15, "Value 4");
tree.insert(25, "Value 5");
tree.insert(12, "Value 6");
tree.insert(18, "Value 7");
tree.insert(22, "Value 8");
std::cout << "Search for key 20: " << (tree.search(20) ? "Found" : "Not found") << std::endl;
std::cout << "Search for key 7: " << (tree.search(7) ? "Found" : "Not found") << std::endl;
return 0;
}