B+树相比于B树,除了有更高的查找性能外,还有更适合范围查询的特点。B+树中只有叶子节点存储了实际的数据,内部节点只是索引。因此,相比于B树,B+树内部节点可以存储更多的索引信息。下面是一个简单的使用C++实现B+树的例子。
#include <iostream>
#include <vector>
using namespace std;
const int MAX_KEY_NUM = 5; // B+树中每个节点最多存储的关键字个数
class BPlusTreeNode {
public:
bool is_leaf; // 是否是叶子节点
int key_num; // 当前节点中关键字的个数
int keys[MAX_KEY_NUM + 1]; // 存储关键字
BPlusTreeNode* parent; // 父节点指针
BPlusTreeNode* children[MAX_KEY_NUM + 2]; // 子节点指针,最多为关键字数+1
BPlusTreeNode() {
is_leaf = false;
key_num = 0;
parent = nullptr;
for (int i = 0; i < MAX_KEY_NUM + 2; i++) {
children[i] = nullptr;
}
}
};
class BPlusTree {
public:
BPlusTreeNode* root;
BPlusTree() {
root = nullptr;
}
BPlusTreeNode* create_node(bool is_leaf) {
BPlusTreeNode* node = new BPlusTreeNode();
node->is_leaf = is_leaf;
return node;
}
void split_child(BPlusTreeNode* parent, int pos, BPlusTreeNode* child) {
BPlusTreeNode* new_child = create_node(child->is_leaf);
new_child->key_num = MAX_KEY_NUM / 2;
for (int i = 0; i < new_child->key_num; i++) {
new_child->keys[i] = child->keys[i + MAX_KEY_NUM / 2];
}
if (!child->is_leaf) {
for (int i = 0; i < MAX_KEY_NUM / 2 + 1; i++) {
new_child->children[i] = child->children[i + MAX_KEY_NUM / 2];
if (new_child->children[i] != nullptr) {
new_child->children[i]->parent = new_child;
}
}
}
child->key_num = MAX_KEY_NUM / 2;
for (int i = parent->key_num; i > pos; i--) {
parent->children[i + 1] = parent->children[i];
}
parent->children[pos + 1] = new_child;
new_child->parent = parent;
for (int i = parent->key_num - 1; i >= pos; i--) {
parent->keys[i + 1] = parent->keys[i];
}
parent->keys[pos] = new_child->keys[0];
parent->key_num++;
}
BPlusTreeNode* insert_node(BPlusTreeNode* node, int key) {
int pos = node->key_num - 1;
if (node->is_leaf) {
while (pos >= 0 && key < node->keys[pos]) {
node->keys[pos + 1] = node->keys[pos];
pos--;
}
node->
keys[pos + 1] = key;
node->key_num++;
}
else {
while (pos >= 0 && key < node->keys[pos]) {
pos--;
}
pos++;
BPlusTreeNode* child = node->children[pos];
if (child->key_num == MAX_KEY_NUM) {
split_child(node, pos, child);
if (key > node->keys[pos]) {
pos++;
child = node->children[pos];
}
}
insert_node(child, key);
}
return node;
}
void insert(int key) {
if (root == nullptr) {
root = create_node(true);
root->keys[0] = key;
root->key_num++;
}
else {
BPlusTreeNode* node = insert_node(root, key);
while (node->parent != nullptr) {
node = node->parent;
}
root = node;
}
}
void print_tree() {
if (root == nullptr) {
return;
}
vector<BPlusTreeNode*> cur_level;
vector<BPlusTreeNode*> next_level;
cur_level.push_back(root);
while (!cur_level.empty()) {
for (int i = 0; i < cur_level.size(); i++) {
BPlusTreeNode* node = cur_level[i];
cout << "(";
for (int j = 0; j < node->key_num; j++) {
cout << node->keys[j];
if (j != node->key_num - 1) {
cout << ",";
}
}
cout << ")";
if (!node->is_leaf) {
for (int j = 0; j < node->key_num + 1; j++) {
if (node->children[j] != nullptr) {
next_level.push_back(node->children[j]);
}
}
}
if (i != cur_level.size() - 1) {
cout << "-";
}
}
cout << endl;
cur_level = next_level;
next_level.clear();
}
}
};
int main() {
BPlusTree tree;
tree.insert(1);
tree.insert(2);
tree.insert(3);
tree.insert(4);
tree.insert(5);
tree.insert(6);
tree.insert(7);
tree.insert(8);
tree.insert(9);
tree.insert(10);
tree.insert(11);
tree.insert(12);
tree.insert(13);
tree.print_tree();
return 0;
}