目录
当然可以。我将为您准备一个详细的学习计划和prompt,来全面讲解B树和B+树的概念、原理、应用及其性能优化等方面。
1. 基本概念
什么是B树和B+树?
B树(B-Tree)是一种平衡多路查找树,它可以保持数据有序,支持快速的插入、删除和数据访问操作。B树的每个节点可以有多个子节点,通常是2到n个。B树的特点是所有叶子节点都在同一层,并且具有相同的深度。
B+树 是B树的一种变种,它在B树的基础上做了一些优化。B+树的特点是所有的数据都存储在叶子节点中,非叶子节点仅存储键值信息,不存储数据。这使得B+树在查询大量数据时更加高效。
B树和B+树的历史背景与发展
B树最早由Rudolf Bayer和Edward M. McCreight在1972年提出,用于解决数据库和文件系统的数据存储问题。
B+树是在B树的基础上发展起来的,主要用于数据库索引和文件系统。
- 节点的定义与属性
- B树的节点可以包含键值对和指向子节点的指针。
- B+树的节点分为内部节点和叶子节点。内部节点仅包含键值信息,叶子节点包含完整的数据记录和指向子节点的指针。
- B树和B+树的区别
- B树的内部节点和叶子节点都存储数据。
- B+树的内部节点不存储数据,仅存储键值信息,所有数据都存储在叶子节点中。
- B+树的叶子节点通过指针相互连接,形成一个链表,便于顺序访问。
3. B树和B+树的操作
插入(Insert)
- 在B树中,插入操作需要找到合适的节点并插入键值对,如果节点满则需要分裂节点。
- 在B+树中,插入操作同样需要找到合适的节点并插入键值对,但仅在叶子节点中插入数据。
- 在B树中,删除操作需要找到键值对并从节点中移除,如果节点不满则可能需要合并节点。
- 在B+树中,删除操作需要找到键值对并从叶子节点中移除,如果节点不满则可能需要从相邻节点借用键值。
查询(Search)
在B树和B+树中,查询操作都是从根节点开始,根据键值信息逐级查找到叶子节点。
4. B树和B+树的平衡性
- 平衡因子
- B树和B+树都需要保持平衡,以确保操作的效率。
- 平衡因子是指节点的子节点数与最大子节点数的比值,通常需要保持在一定范围内。
- 平衡操作
- 当节点分裂或合并时,需要进行平衡操作以保持树的平衡。
- 优势:磁盘读写效率高、查询性能好等
- 磁盘读写效率高:B树和B+树通过减少磁盘I/O操作次数提高了效率。
- 查询性能好:有序的数据结构使得查询操作更加高效。
- 劣势:实现复杂度较高等
- 实现复杂度较高:相比于简单的数据结构,B树和B+树的实现较为复杂。
6. 实际应用
- B树和B+树广泛应用于数据库索引,如MySQL、PostgreSQL等。
- 通过索引可以加速数据的查询和更新操作。
- 适用场景与案例分析
7. 性能优化
- 缓存策略
- 通过缓存常用数据可以减少对磁盘的访问,提高系统性能。
- 查询优化
- 优化查询算法,减少不必要的磁盘访问,提高查询效率。
- 简单的B树和B+树实现
B树代码实现
#include <iostream>
#include <vector>
#include <algorithm>
class BTreeNode {
public:
BTreeNode(int t, bool leaf);
void traverse();
BTreeNode *search(int k);
void insertNonFull(int k);
void splitChild(int i, BTreeNode *y);
std::vector<int> keys;
std::vector<BTreeNode*> children;
int t;
bool leaf;
};
class BTree {
public:
BTree(int t);
void traverse();
BTreeNode* search(int k);
void insert(int k);
private:
BTreeNode *root;
int t;
};
BTreeNode::BTreeNode(int t, bool leaf) : t(t), leaf(leaf) {}
void BTreeNode::traverse() {
int i;
for (i = 0; i < keys.size(); i++) {
if (!leaf) {
children[i]->traverse();
}
std::cout << " " << keys[i];
}
if (!leaf) {
children[i]->traverse();
}
}
BTreeNode* BTreeNode::search(int k) {
int i = 0;
while (i < keys.size() && k > keys[i]) {
i++;
}
if (i < keys.size() && keys[i] == k) {
return this;
}
if (leaf) {
return nullptr;
}
return children[i]->search(k);
}
void BTreeNode::insertNonFull(int k) {
int i = keys.size() - 1;
if (leaf) {
keys.insert(keys.begin() + i + 1, k);
while (i >= 0 && keys[i] > k) {
keys[i + 1] = keys[i];
i--;
}
keys[i + 1] = k;
} else {
while (i >= 0 && keys[i] > k) {
i--;
}
if (children[i + 1]->keys.size() == 2 * t - 1) {
splitChild(i + 1, children[i + 1]);
if (keys[i + 1] < k) {
i++;
}
}
children[i + 1]->insertNonFull(k);
}
}
void BTreeNode::splitChild(int i, BTreeNode *y) {
BTreeNode *z = new BTreeNode(y->t, y->leaf);
z->keys.resize(t - 1);
for (int j = 0; j < t - 1; j++) {
z->keys[j] = y->keys[j + t];
}
if (!y->leaf) {
z->children.resize(t);
for (int j = 0; j < t; j++) {
z->children[j] = y->children[j + t];
}
}
y->keys.resize(t - 1);
children.insert(children.begin() + i + 1, z);
keys.insert(keys.begin() + i, y->keys[t - 1]);
}
BTree::BTree(int t) : t(t) {
root = new BTreeNode(t, true);
}
void BTree::traverse() {
if (root != nullptr) {
root->traverse();
}
}
BTreeNode* BTree::search(int k) {
return (root == nullptr) ? nullptr : root->search(k);
}
void BTree::insert(int k) {
if (root->keys.size() == 2 * t - 1) {
BTreeNode *s = new BTreeNode(t, false);
s->children.push_back(root);
s->splitChild(0, root);
int i = 0;
if (s->keys[0] < k) {
i++;
}
s->children[i]->insertNonFull(k);
root = s;
} else {
root->insertNonFull(k);
}
}
int main() {
BTree t(3);
t.insert(10);
t.insert(20);
t.insert(5);
t.insert(6);
t.insert(12);
t.insert(30);
t.insert(7);
t.insert(17);
std::cout << "Traversal of the constructed tree is: ";
t.traverse();
int key = 6;
if (t.search(key) != nullptr) {
std::cout << "\nKey " << key << " is present in the tree.";
} else {
std::cout << "\nKey " << key << " is not present in the tree.";
}
key = 15;
if (t.search(key) != nullptr) {
std::cout << "\nKey " << key << " is present in the tree.";
} else {
std::cout << "\nKey " << key << " is not present in the tree.";
}
return 0;
}
B+树的实现
#include <iostream>
#include <vector>
#include <algorithm>
class BPlusTreeNode {
public:
BPlusTreeNode(bool leaf);
void insertNonFull(int k, int v);
void splitChild(int i, BPlusTreeNode *y);
void traverse();
BPlusTreeNode* search(int k);
int get(int k);
std::vector<int> keys;
std::vector<int> values; // 仅在叶子节点中使用
std::vector<BPlusTreeNode*> children;
BPlusTreeNode* next; // 仅在叶子节点中使用
int t;
bool leaf;
};
class BPlusTree {
public:
BPlusTree(int t);
void traverse();
int search(int k);
void insert(int k, int v);
private:
BPlusTreeNode *root;
int t;
};
BPlusTreeNode::BPlusTreeNode(bool leaf) : leaf(leaf), next(nullptr) {}
void BPlusTreeNode::traverse() {
if (leaf) {
for (int i = 0; i < keys.size(); i++) {
std::cout << " (" << keys[i] << ", " << values[i] << ")";
}
if (next) {
next->traverse();
}
} else {
for (int i = 0; i < keys.size(); i++) {
children[i]->traverse();
std::cout << " " << keys[i];
}
children[keys.size()]->traverse();
}
}
BPlusTreeNode* BPlusTreeNode::search(int k) {
int i = 0;
while (i < keys.size() && k > keys[i]) {
i++;
}
if (leaf) {
return (i < keys.size() && keys[i] == k) ? this : nullptr;
} else {
return children[i]->search(k);
}
}
int BPlusTreeNode::get(int k) {
int i = 0;
while (i < keys.size() && k > keys[i]) {
i++;
}
if (i < keys.size() && keys[i] == k) {
return values[i];
}
return -1; // 未找到
}
void BPlusTreeNode::insertNonFull(int k, int v) {
int i = keys.size() - 1;
if (leaf) {
keys.push_back(k);
values.push_back(v);
while (i >= 0 && keys[i] > k) {
keys[i + 1] = keys[i];
values[i + 1] = values[i];
i--;
}
keys[i + 1] = k;
values[i + 1] = v;
} else {
while (i >= 0 && keys[i] > k) {
i--;
}
if (children[i + 1]->keys.size() == 2 * t - 1) {
splitChild(i + 1, children[i + 1]);
if (keys[i + 1] < k) {
i++;
}
}
children[i + 1]->insertNonFull(k, v);
}
}
void BPlusTreeNode::splitChild(int i, BPlusTreeNode *y) {
BPlusTreeNode *z = new BPlusTreeNode(y->leaf);
z->t = y->t;
for (int j = 0; j < t - 1; j++) {
z->keys.push_back(y->keys[j + t]);
if (y->leaf) {
z->values.push_back(y->values[j + t]);
}
}
if (!y->leaf) {
for (int j = 0; j < t; j++) {
z->children.push_back(y->children[j + t]);
}
} else {
z->next = y->next;
y->next = z;
}
y->keys.resize(t - 1);
if (y->leaf) {
y->values.resize(t - 1);
}
children.insert(children.begin() + i + 1, z);
keys.insert(keys.begin() + i, y->keys[t - 1]);
}
BPlusTree::BPlusTree(int t) : t(t) {
root = new BPlusTreeNode(true);
root->t = t;
}
void BPlusTree::traverse() {
if (root != nullptr) {
root->traverse();
}
}
int BPlusTree::search(int k) {
BPlusTreeNode* node = (root == nullptr) ? nullptr : root->search(k);
return (node == nullptr) ? -1 : node->get(k);
}
void BPlusTree::insert(int k, int v) {
if (root->keys.size() == 2 * t - 1) {
BPlusTreeNode *s = new BPlusTreeNode(false);
s->t = t;
s->children.push_back(root);
s->splitChild(0, root);
int i = 0;
if (s->keys[0] < k) {
i++;
}
s->children[i]->insertNonFull(k, v);
root = s;
} else {
root->insertNonFull(k, v);
}
}
9. 参考资料
- [原始论文: B-Trees](https://cs.stanford.edu/~mjkay/courses/cs345_spring10/papers/knuth73.pdf)
- [原始论文: The B+-Tree: A New Data Structure for Database and Information Retrieval Systems](https://www.semanticscholar.org/paper/The-B+-Tree-%3A-A-New-Data-Structure-for-Database-Comer/2d24b89de4eb2c1b5064bbf28ed2b6a59ac8f312)
- [MySQL](https://dev.mysql.com/doc/internals/en/b-tree-index.html)
- [PostgreSQL](https://www.postgresql.org/docs/current/indexes-types.html)
什么是B树和B+树?
B树(B-Tree)是一种平衡多路查找树,它可以保持数据有序,支持快速的插入、删除和数据访问操作。B树的每个节点可以有多个子节点,通常是2到n个。B树的特点是所有叶子节点都在同一层,并且具有相同的深度。
B+树 是B树的一种变种,它在B树的基础上做了一些优化。B+树的特点是所有的数据都存储在叶子节点中,非叶子节点仅存储键值信息,不存储数据。这使得B+树在查询大量数据时更加高效。
B树和B+树的历史背景与发展
B树最早由Rudolf Bayer和Edward M. McCreight在1972年提出,用于解决数据库和文件系统的数据存储问题。
B+树是在B树的基础上发展起来的,主要用于数据库索引和文件系统。
- 节点的定义与属性
- B树的节点可以包含键值对和指向子节点的指针。
- B+树的节点分为内部节点和叶子节点。内部节点仅包含键值信息,叶子节点包含完整的数据记录和指向子节点的指针。
- B树和B+树的区别
- B树的内部节点和叶子节点都存储数据。
- B+树的内部节点不存储数据,仅存储键值信息,所有数据都存储在叶子节点中。
- B+树的叶子节点通过指针相互连接,形成一个链表,便于顺序访问。
3. B树和B+树的操作
- 在B树中,插入操作需要找到合适的节点并插入键值对,如果节点满则需要分裂节点。
- 在B+树中,插入操作同样需要找到合适的节点并插入键值对,但仅在叶子节点中插入数据。
- 在B树中,删除操作需要找到键值对并从节点中移除,如果节点不满则可能需要合并节点。
- 在B+树中,删除操作需要找到键值对并从叶子节点中移除,如果节点不满则可能需要从相邻节点借用键值。
查询(Search)
在B树和B+树中,查询操作都是从根节点开始,根据键值信息逐级查找到叶子节点。
插入(Insert)
4. B树和B+树的平衡性
- 平衡因子
- B树和B+树都需要保持平衡,以确保操作的效率。
- 平衡因子是指节点的子节点数与最大子节点数的比值,通常需要保持在一定范围内。
- 平衡操作
- 当节点分裂或合并时,需要进行平衡操作以保持树的平衡。
- 优势:磁盘读写效率高、查询性能好等
- 磁盘读写效率高:B树和B+树通过减少磁盘I/O操作次数提高了效率。
- 查询性能好:有序的数据结构使得查询操作更加高效。
- 劣势:实现复杂度较高等
- 实现复杂度较高:相比于简单的数据结构,B树和B+树的实现较为复杂。
6. 实际应用
- B树和B+树广泛应用于数据库索引,如MySQL、PostgreSQL等。
- 通过索引可以加速数据的查询和更新操作。
- 适用场景与案例分析
7. 性能优化
- 缓存策略
- 通过缓存常用数据可以减少对磁盘的访问,提高系统性能。
- 查询优化
- 优化查询算法,减少不必要的磁盘访问,提高查询效率。
- 简单的B树和B+树实现
B树代码实现
#include <iostream>
#include <vector>
#include <algorithm>
class BTreeNode {
public:
BTreeNode(int t, bool leaf);
void traverse();
BTreeNode *search(int k);
void insertNonFull(int k);
void splitChild(int i, BTreeNode *y);
std::vector<int> keys;
std::vector<BTreeNode*> children;
int t;
bool leaf;
};
class BTree {
public:
BTree(int t);
void traverse();
BTreeNode* search(int k);
void insert(int k);
private:
BTreeNode *root;
int t;
};
BTreeNode::BTreeNode(int t, bool leaf) : t(t), leaf(leaf) {}
void BTreeNode::traverse() {
int i;
for (i = 0; i < keys.size(); i++) {
if (!leaf) {
children[i]->traverse();
}
std::cout << " " << keys[i];
}
if (!leaf) {
children[i]->traverse();
}
}
BTreeNode* BTreeNode::search(int k) {
int i = 0;
while (i < keys.size() && k > keys[i]) {
i++;
}
if (i < keys.size() && keys[i] == k) {
return this;
}
if (leaf) {
return nullptr;
}
return children[i]->search(k);
}
void BTreeNode::insertNonFull(int k) {
int i = keys.size() - 1;
if (leaf) {
keys.insert(keys.begin() + i + 1, k);
while (i >= 0 && keys[i] > k) {
keys[i + 1] = keys[i];
i--;
}
keys[i + 1] = k;
} else {
while (i >= 0 && keys[i] > k) {
i--;
}
if (children[i + 1]->keys.size() == 2 * t - 1) {
splitChild(i + 1, children[i + 1]);
if (keys[i + 1] < k) {
i++;
}
}
children[i + 1]->insertNonFull(k);
}
}
void BTreeNode::splitChild(int i, BTreeNode *y) {
BTreeNode *z = new BTreeNode(y->t, y->leaf);
z->keys.resize(t - 1);
for (int j = 0; j < t - 1; j++) {
z->keys[j] = y->keys[j + t];
}
if (!y->leaf) {
z->children.resize(t);
for (int j = 0; j < t; j++) {
z->children[j] = y->children[j + t];
}
}
y->keys.resize(t - 1);
children.insert(children.begin() + i + 1, z);
keys.insert(keys.begin() + i, y->keys[t - 1]);
}
BTree::BTree(int t) : t(t) {
root = new BTreeNode(t, true);
}
void BTree::traverse() {
if (root != nullptr) {
root->traverse();
}
}
BTreeNode* BTree::search(int k) {
return (root == nullptr) ? nullptr : root->search(k);
}
void BTree::insert(int k) {
if (root->keys.size() == 2 * t - 1) {
BTreeNode *s = new BTreeNode(t, false);
s->children.push_back(root);
s->splitChild(0, root);
int i = 0;
if (s->keys[0] < k) {
i++;
}
s->children[i]->insertNonFull(k);
root = s;
} else {
root->insertNonFull(k);
}
}
int main() {
BTree t(3);
t.insert(10);
t.insert(20);
t.insert(5);
t.insert(6);
t.insert(12);
t.insert(30);
t.insert(7);
t.insert(17);
std::cout << "Traversal of the constructed tree is: ";
t.traverse();
int key = 6;
if (t.search(key) != nullptr) {
std::cout << "\nKey " << key << " is present in the tree.";
} else {
std::cout << "\nKey " << key << " is not present in the tree.";
}
key = 15;
if (t.search(key) != nullptr) {
std::cout << "\nKey " << key << " is present in the tree.";
} else {
std::cout << "\nKey " << key << " is not present in the tree.";
}
return 0;
}
B+树的实现
#include <iostream>
#include <vector>
#include <algorithm>
class BPlusTreeNode {
public:
BPlusTreeNode(bool leaf);
void insertNonFull(int k, int v);
void splitChild(int i, BPlusTreeNode *y);
void traverse();
BPlusTreeNode* search(int k);
int get(int k);
std::vector<int> keys;
std::vector<int> values; // 仅在叶子节点中使用
std::vector<BPlusTreeNode*> children;
BPlusTreeNode* next; // 仅在叶子节点中使用
int t;
bool leaf;
};
class BPlusTree {
public:
BPlusTree(int t);
void traverse();
int search(int k);
void insert(int k, int v);
private:
BPlusTreeNode *root;
int t;
};
BPlusTreeNode::BPlusTreeNode(bool leaf) : leaf(leaf), next(nullptr) {}
void BPlusTreeNode::traverse() {
if (leaf) {
for (int i = 0; i < keys.size(); i++) {
std::cout << " (" << keys[i] << ", " << values[i] << ")";
}
if (next) {
next->traverse();
}
} else {
for (int i = 0; i < keys.size(); i++) {
children[i]->traverse();
std::cout << " " << keys[i];
}
children[keys.size()]->traverse();
}
}
BPlusTreeNode* BPlusTreeNode::search(int k) {
int i = 0;
while (i < keys.size() && k > keys[i]) {
i++;
}
if (leaf) {
return (i < keys.size() && keys[i] == k) ? this : nullptr;
} else {
return children[i]->search(k);
}
}
int BPlusTreeNode::get(int k) {
int i = 0;
while (i < keys.size() && k > keys[i]) {
i++;
}
if (i < keys.size() && keys[i] == k) {
return values[i];
}
return -1; // 未找到
}
void BPlusTreeNode::insertNonFull(int k, int v) {
int i = keys.size() - 1;
if (leaf) {
keys.push_back(k);
values.push_back(v);
while (i >= 0 && keys[i] > k) {
keys[i + 1] = keys[i];
values[i + 1] = values[i];
i--;
}
keys[i + 1] = k;
values[i + 1] = v;
} else {
while (i >= 0 && keys[i] > k) {
i--;
}
if (children[i + 1]->keys.size() == 2 * t - 1) {
splitChild(i + 1, children[i + 1]);
if (keys[i + 1] < k) {
i++;
}
}
children[i + 1]->insertNonFull(k, v);
}
}
void BPlusTreeNode::splitChild(int i, BPlusTreeNode *y) {
BPlusTreeNode *z = new BPlusTreeNode(y->leaf);
z->t = y->t;
for (int j = 0; j < t - 1; j++) {
z->keys.push_back(y->keys[j + t]);
if (y->leaf) {
z->values.push_back(y->values[j + t]);
}
}
if (!y->leaf) {
for (int j = 0; j < t; j++) {
z->children.push_back(y->children[j + t]);
}
} else {
z->next = y->next;
y->next = z;
}
y->keys.resize(t - 1);
if (y->leaf) {
y->values.resize(t - 1);
}
children.insert(children.begin() + i + 1, z);
keys.insert(keys.begin() + i, y->keys[t - 1]);
}
BPlusTree::BPlusTree(int t) : t(t) {
root = new BPlusTreeNode(true);
root->t = t;
}
void BPlusTree::traverse() {
if (root != nullptr) {
root->traverse();
}
}
int BPlusTree::search(int k) {
BPlusTreeNode* node = (root == nullptr) ? nullptr : root->search(k);
return (node == nullptr) ? -1 : node->get(k);
}
void BPlusTree::insert(int k, int v) {
if (root->keys.size() == 2 * t - 1) {
BPlusTreeNode *s = new BPlusTreeNode(false);
s->t = t;
s->children.push_back(root);
s->splitChild(0, root);
int i = 0;
if (s->keys[0] < k) {
i++;
}
s->children[i]->insertNonFull(k, v);
root = s;
} else {
root->insertNonFull(k, v);
}
}
9. 参考资料
- [原始论文: B-Trees](https://cs.stanford.edu/~mjkay/courses/cs345_spring10/papers/knuth73.pdf)
- [原始论文: The B+-Tree: A New Data Structure for Database and Information Retrieval Systems](https://www.semanticscholar.org/paper/The-B+-Tree-%3A-A-New-Data-Structure-for-Database-Comer/2d24b89de4eb2c1b5064bbf28ed2b6a59ac8f312)
- [MySQL](https://dev.mysql.com/doc/internals/en/b-tree-index.html)
- [PostgreSQL](https://www.postgresql.org/docs/current/indexes-types.html)
- 磁盘读写效率高:B树和B+树通过减少磁盘I/O操作次数提高了效率。
- 查询性能好:有序的数据结构使得查询操作更加高效。
- 实现复杂度较高:相比于简单的数据结构,B树和B+树的实现较为复杂。
- B树和B+树广泛应用于数据库索引,如MySQL、PostgreSQL等。
- 通过索引可以加速数据的查询和更新操作。
- 缓存策略
- 通过缓存常用数据可以减少对磁盘的访问,提高系统性能。
- 查询优化
- 优化查询算法,减少不必要的磁盘访问,提高查询效率。
- 简单的B树和B+树实现
7. 性能优化
B树代码实现
#include <iostream>
#include <vector>
#include <algorithm>
class BTreeNode {
public:
BTreeNode(int t, bool leaf);
void traverse();
BTreeNode *search(int k);
void insertNonFull(int k);
void splitChild(int i, BTreeNode *y);
std::vector<int> keys;
std::vector<BTreeNode*> children;
int t;
bool leaf;
};
class BTree {
public:
BTree(int t);
void traverse();
BTreeNode* search(int k);
void insert(int k);
private:
BTreeNode *root;
int t;
};
BTreeNode::BTreeNode(int t, bool leaf) : t(t), leaf(leaf) {}
void BTreeNode::traverse() {
int i;
for (i = 0; i < keys.size(); i++) {
if (!leaf) {
children[i]->traverse();
}
std::cout << " " << keys[i];
}
if (!leaf) {
children[i]->traverse();
}
}
BTreeNode* BTreeNode::search(int k) {
int i = 0;
while (i < keys.size() && k > keys[i]) {
i++;
}
if (i < keys.size() && keys[i] == k) {
return this;
}
if (leaf) {
return nullptr;
}
return children[i]->search(k);
}
void BTreeNode::insertNonFull(int k) {
int i = keys.size() - 1;
if (leaf) {
keys.insert(keys.begin() + i + 1, k);
while (i >= 0 && keys[i] > k) {
keys[i + 1] = keys[i];
i--;
}
keys[i + 1] = k;
} else {
while (i >= 0 && keys[i] > k) {
i--;
}
if (children[i + 1]->keys.size() == 2 * t - 1) {
splitChild(i + 1, children[i + 1]);
if (keys[i + 1] < k) {
i++;
}
}
children[i + 1]->insertNonFull(k);
}
}
void BTreeNode::splitChild(int i, BTreeNode *y) {
BTreeNode *z = new BTreeNode(y->t, y->leaf);
z->keys.resize(t - 1);
for (int j = 0; j < t - 1; j++) {
z->keys[j] = y->keys[j + t];
}
if (!y->leaf) {
z->children.resize(t);
for (int j = 0; j < t; j++) {
z->children[j] = y->children[j + t];
}
}
y->keys.resize(t - 1);
children.insert(children.begin() + i + 1, z);
keys.insert(keys.begin() + i, y->keys[t - 1]);
}
BTree::BTree(int t) : t(t) {
root = new BTreeNode(t, true);
}
void BTree::traverse() {
if (root != nullptr) {
root->traverse();
}
}
BTreeNode* BTree::search(int k) {
return (root == nullptr) ? nullptr : root->search(k);
}
void BTree::insert(int k) {
if (root->keys.size() == 2 * t - 1) {
BTreeNode *s = new BTreeNode(t, false);
s->children.push_back(root);
s->splitChild(0, root);
int i = 0;
if (s->keys[0] < k) {
i++;
}
s->children[i]->insertNonFull(k);
root = s;
} else {
root->insertNonFull(k);
}
}
int main() {
BTree t(3);
t.insert(10);
t.insert(20);
t.insert(5);
t.insert(6);
t.insert(12);
t.insert(30);
t.insert(7);
t.insert(17);
std::cout << "Traversal of the constructed tree is: ";
t.traverse();
int key = 6;
if (t.search(key) != nullptr) {
std::cout << "\nKey " << key << " is present in the tree.";
} else {
std::cout << "\nKey " << key << " is not present in the tree.";
}
key = 15;
if (t.search(key) != nullptr) {
std::cout << "\nKey " << key << " is present in the tree.";
} else {
std::cout << "\nKey " << key << " is not present in the tree.";
}
return 0;
}
B+树的实现
#include <iostream>
#include <vector>
#include <algorithm>
class BPlusTreeNode {
public:
BPlusTreeNode(bool leaf);
void insertNonFull(int k, int v);
void splitChild(int i, BPlusTreeNode *y);
void traverse();
BPlusTreeNode* search(int k);
int get(int k);
std::vector<int> keys;
std::vector<int> values; // 仅在叶子节点中使用
std::vector<BPlusTreeNode*> children;
BPlusTreeNode* next; // 仅在叶子节点中使用
int t;
bool leaf;
};
class BPlusTree {
public:
BPlusTree(int t);
void traverse();
int search(int k);
void insert(int k, int v);
private:
BPlusTreeNode *root;
int t;
};
BPlusTreeNode::BPlusTreeNode(bool leaf) : leaf(leaf), next(nullptr) {}
void BPlusTreeNode::traverse() {
if (leaf) {
for (int i = 0; i < keys.size(); i++) {
std::cout << " (" << keys[i] << ", " << values[i] << ")";
}
if (next) {
next->traverse();
}
} else {
for (int i = 0; i < keys.size(); i++) {
children[i]->traverse();
std::cout << " " << keys[i];
}
children[keys.size()]->traverse();
}
}
BPlusTreeNode* BPlusTreeNode::search(int k) {
int i = 0;
while (i < keys.size() && k > keys[i]) {
i++;
}
if (leaf) {
return (i < keys.size() && keys[i] == k) ? this : nullptr;
} else {
return children[i]->search(k);
}
}
int BPlusTreeNode::get(int k) {
int i = 0;
while (i < keys.size() && k > keys[i]) {
i++;
}
if (i < keys.size() && keys[i] == k) {
return values[i];
}
return -1; // 未找到
}
void BPlusTreeNode::insertNonFull(int k, int v) {
int i = keys.size() - 1;
if (leaf) {
keys.push_back(k);
values.push_back(v);
while (i >= 0 && keys[i] > k) {
keys[i + 1] = keys[i];
values[i + 1] = values[i];
i--;
}
keys[i + 1] = k;
values[i + 1] = v;
} else {
while (i >= 0 && keys[i] > k) {
i--;
}
if (children[i + 1]->keys.size() == 2 * t - 1) {
splitChild(i + 1, children[i + 1]);
if (keys[i + 1] < k) {
i++;
}
}
children[i + 1]->insertNonFull(k, v);
}
}
void BPlusTreeNode::splitChild(int i, BPlusTreeNode *y) {
BPlusTreeNode *z = new BPlusTreeNode(y->leaf);
z->t = y->t;
for (int j = 0; j < t - 1; j++) {
z->keys.push_back(y->keys[j + t]);
if (y->leaf) {
z->values.push_back(y->values[j + t]);
}
}
if (!y->leaf) {
for (int j = 0; j < t; j++) {
z->children.push_back(y->children[j + t]);
}
} else {
z->next = y->next;
y->next = z;
}
y->keys.resize(t - 1);
if (y->leaf) {
y->values.resize(t - 1);
}
children.insert(children.begin() + i + 1, z);
keys.insert(keys.begin() + i, y->keys[t - 1]);
}
BPlusTree::BPlusTree(int t) : t(t) {
root = new BPlusTreeNode(true);
root->t = t;
}
void BPlusTree::traverse() {
if (root != nullptr) {
root->traverse();
}
}
int BPlusTree::search(int k) {
BPlusTreeNode* node = (root == nullptr) ? nullptr : root->search(k);
return (node == nullptr) ? -1 : node->get(k);
}
void BPlusTree::insert(int k, int v) {
if (root->keys.size() == 2 * t - 1) {
BPlusTreeNode *s = new BPlusTreeNode(false);
s->t = t;
s->children.push_back(root);
s->splitChild(0, root);
int i = 0;
if (s->keys[0] < k) {
i++;
}
s->children[i]->insertNonFull(k, v);
root = s;
} else {
root->insertNonFull(k, v);
}
}
9. 参考资料
- [原始论文: B-Trees](https://cs.stanford.edu/~mjkay/courses/cs345_spring10/papers/knuth73.pdf)
- [原始论文: The B+-Tree: A New Data Structure for Database and Information Retrieval Systems](https://www.semanticscholar.org/paper/The-B+-Tree-%3A-A-New-Data-Structure-for-Database-Comer/2d24b89de4eb2c1b5064bbf28ed2b6a59ac8f312)
- [MySQL](https://dev.mysql.com/doc/internals/en/b-tree-index.html)
- [PostgreSQL](https://www.postgresql.org/docs/current/indexes-types.html)
#include <iostream>
#include <vector>
#include <algorithm>
class BTreeNode {
public:
BTreeNode(int t, bool leaf);
void traverse();
BTreeNode *search(int k);
void insertNonFull(int k);
void splitChild(int i, BTreeNode *y);
std::vector<int> keys;
std::vector<BTreeNode*> children;
int t;
bool leaf;
};
class BTree {
public:
BTree(int t);
void traverse();
BTreeNode* search(int k);
void insert(int k);
private:
BTreeNode *root;
int t;
};
BTreeNode::BTreeNode(int t, bool leaf) : t(t), leaf(leaf) {}
void BTreeNode::traverse() {
int i;
for (i = 0; i < keys.size(); i++) {
if (!leaf) {
children[i]->traverse();
}
std::cout << " " << keys[i];
}
if (!leaf) {
children[i]->traverse();
}
}
BTreeNode* BTreeNode::search(int k) {
int i = 0;
while (i < keys.size() && k > keys[i]) {
i++;
}
if (i < keys.size() && keys[i] == k) {
return this;
}
if (leaf) {
return nullptr;
}
return children[i]->search(k);
}
void BTreeNode::insertNonFull(int k) {
int i = keys.size() - 1;
if (leaf) {
keys.insert(keys.begin() + i + 1, k);
while (i >= 0 && keys[i] > k) {
keys[i + 1] = keys[i];
i--;
}
keys[i + 1] = k;
} else {
while (i >= 0 && keys[i] > k) {
i--;
}
if (children[i + 1]->keys.size() == 2 * t - 1) {
splitChild(i + 1, children[i + 1]);
if (keys[i + 1] < k) {
i++;
}
}
children[i + 1]->insertNonFull(k);
}
}
void BTreeNode::splitChild(int i, BTreeNode *y) {
BTreeNode *z = new BTreeNode(y->t, y->leaf);
z->keys.resize(t - 1);
for (int j = 0; j < t - 1; j++) {
z->keys[j] = y->keys[j + t];
}
if (!y->leaf) {
z->children.resize(t);
for (int j = 0; j < t; j++) {
z->children[j] = y->children[j + t];
}
}
y->keys.resize(t - 1);
children.insert(children.begin() + i + 1, z);
keys.insert(keys.begin() + i, y->keys[t - 1]);
}
BTree::BTree(int t) : t(t) {
root = new BTreeNode(t, true);
}
void BTree::traverse() {
if (root != nullptr) {
root->traverse();
}
}
BTreeNode* BTree::search(int k) {
return (root == nullptr) ? nullptr : root->search(k);
}
void BTree::insert(int k) {
if (root->keys.size() == 2 * t - 1) {
BTreeNode *s = new BTreeNode(t, false);
s->children.push_back(root);
s->splitChild(0, root);
int i = 0;
if (s->keys[0] < k) {
i++;
}
s->children[i]->insertNonFull(k);
root = s;
} else {
root->insertNonFull(k);
}
}
int main() {
BTree t(3);
t.insert(10);
t.insert(20);
t.insert(5);
t.insert(6);
t.insert(12);
t.insert(30);
t.insert(7);
t.insert(17);
std::cout << "Traversal of the constructed tree is: ";
t.traverse();
int key = 6;
if (t.search(key) != nullptr) {
std::cout << "\nKey " << key << " is present in the tree.";
} else {
std::cout << "\nKey " << key << " is not present in the tree.";
}
key = 15;
if (t.search(key) != nullptr) {
std::cout << "\nKey " << key << " is present in the tree.";
} else {
std::cout << "\nKey " << key << " is not present in the tree.";
}
return 0;
}
#include <iostream>
#include <vector>
#include <algorithm>
class BPlusTreeNode {
public:
BPlusTreeNode(bool leaf);
void insertNonFull(int k, int v);
void splitChild(int i, BPlusTreeNode *y);
void traverse();
BPlusTreeNode* search(int k);
int get(int k);
std::vector<int> keys;
std::vector<int> values; // 仅在叶子节点中使用
std::vector<BPlusTreeNode*> children;
BPlusTreeNode* next; // 仅在叶子节点中使用
int t;
bool leaf;
};
class BPlusTree {
public:
BPlusTree(int t);
void traverse();
int search(int k);
void insert(int k, int v);
private:
BPlusTreeNode *root;
int t;
};
BPlusTreeNode::BPlusTreeNode(bool leaf) : leaf(leaf), next(nullptr) {}
void BPlusTreeNode::traverse() {
if (leaf) {
for (int i = 0; i < keys.size(); i++) {
std::cout << " (" << keys[i] << ", " << values[i] << ")";
}
if (next) {
next->traverse();
}
} else {
for (int i = 0; i < keys.size(); i++) {
children[i]->traverse();
std::cout << " " << keys[i];
}
children[keys.size()]->traverse();
}
}
BPlusTreeNode* BPlusTreeNode::search(int k) {
int i = 0;
while (i < keys.size() && k > keys[i]) {
i++;
}
if (leaf) {
return (i < keys.size() && keys[i] == k) ? this : nullptr;
} else {
return children[i]->search(k);
}
}
int BPlusTreeNode::get(int k) {
int i = 0;
while (i < keys.size() && k > keys[i]) {
i++;
}
if (i < keys.size() && keys[i] == k) {
return values[i];
}
return -1; // 未找到
}
void BPlusTreeNode::insertNonFull(int k, int v) {
int i = keys.size() - 1;
if (leaf) {
keys.push_back(k);
values.push_back(v);
while (i >= 0 && keys[i] > k) {
keys[i + 1] = keys[i];
values[i + 1] = values[i];
i--;
}
keys[i + 1] = k;
values[i + 1] = v;
} else {
while (i >= 0 && keys[i] > k) {
i--;
}
if (children[i + 1]->keys.size() == 2 * t - 1) {
splitChild(i + 1, children[i + 1]);
if (keys[i + 1] < k) {
i++;
}
}
children[i + 1]->insertNonFull(k, v);
}
}
void BPlusTreeNode::splitChild(int i, BPlusTreeNode *y) {
BPlusTreeNode *z = new BPlusTreeNode(y->leaf);
z->t = y->t;
for (int j = 0; j < t - 1; j++) {
z->keys.push_back(y->keys[j + t]);
if (y->leaf) {
z->values.push_back(y->values[j + t]);
}
}
if (!y->leaf) {
for (int j = 0; j < t; j++) {
z->children.push_back(y->children[j + t]);
}
} else {
z->next = y->next;
y->next = z;
}
y->keys.resize(t - 1);
if (y->leaf) {
y->values.resize(t - 1);
}
children.insert(children.begin() + i + 1, z);
keys.insert(keys.begin() + i, y->keys[t - 1]);
}
BPlusTree::BPlusTree(int t) : t(t) {
root = new BPlusTreeNode(true);
root->t = t;
}
void BPlusTree::traverse() {
if (root != nullptr) {
root->traverse();
}
}
int BPlusTree::search(int k) {
BPlusTreeNode* node = (root == nullptr) ? nullptr : root->search(k);
return (node == nullptr) ? -1 : node->get(k);
}
void BPlusTree::insert(int k, int v) {
if (root->keys.size() == 2 * t - 1) {
BPlusTreeNode *s = new BPlusTreeNode(false);
s->t = t;
s->children.push_back(root);
s->splitChild(0, root);
int i = 0;
if (s->keys[0] < k) {
i++;
}
s->children[i]->insertNonFull(k, v);
root = s;
} else {
root->insertNonFull(k, v);
}
}
9. 参考资料
- [原始论文: B-Trees](https://cs.stanford.edu/~mjkay/courses/cs345_spring10/papers/knuth73.pdf)
- [原始论文: The B+-Tree: A New Data Structure for Database and Information Retrieval Systems](https://www.semanticscholar.org/paper/The-B+-Tree-%3A-A-New-Data-Structure-for-Database-Comer/2d24b89de4eb2c1b5064bbf28ed2b6a59ac8f312)
- [MySQL](https://dev.mysql.com/doc/internals/en/b-tree-index.html)
- [PostgreSQL](https://www.postgresql.org/docs/current/indexes-types.html)
No comments yet.