B树(B-tree)c++语言
B树可以自平衡,这意味着每次插入和删除操作后,B树都可以通过旋转和重构节点来保持平衡。这种自平衡的特性使得B树可以应对动态的数据存储需求,同时保持高效的查询和修改操作。B树的节点大小通常和磁盘块大小相同,因此可以直接在磁盘上存储B树。B树可以存储大量的数据,因为它可以在节点中存储多个关键字和指向子节点的指针。B树的查询和修改操作的时间复杂度为O(log n),其中n是B树中存储的关键字数量。因此,
·
B树(B-tree)是一种自平衡的树形数据结构,用于存储和管理大量数据。它被广泛应用于文件系统和数据库管理系统中。
B树具有以下几个优点:
-
支持快速的查找、插入和删除操作。B树的查询和修改操作的时间复杂度为O(log n),其中n是B树中存储的关键字数量。
-
B树可以存储大量的数据,因为它可以在节点中存储多个关键字和指向子节点的指针。这使得B树比二叉查找树更加适合存储大规模的数据。
-
B树的节点大小通常和磁盘块大小相同,因此可以直接在磁盘上存储B树。这种优化可以减少磁盘I/O操作的次数,从而提高查询和修改操作的效率。
-
B树可以自平衡,这意味着每次插入和删除操作后,B树都可以通过旋转和重构节点来保持平衡。这种自平衡的特性使得B树可以应对动态的数据存储需求,同时保持高效的查询和修改操作。
因此,B树被广泛应用于文件系统、数据库管理系统、存储系统和其他需要高效存储和管理大量数据的应用中。
下面使用c++语言描述一下B树
#include <iostream>
#include <vector>
using namespace std;
const int MAX_CHILDREN_NUM = 4;
const int MIN_CHILDREN_NUM = 2;
const int MAX_KEY_NUM = 3;
const int MIN_KEY_NUM = 1;
struct BTreeNode {
vector<int> keys; // 存储关键字的向量
vector<BTreeNode*> children; // 存储指向子节点的指针的向量
BTreeNode* parent; // 指向父节点的指针
bool is_leaf; // 是否为叶子节点
int key_num; // 关键字数量
BTreeNode() {
keys.resize(MAX_KEY_NUM);
children.resize(MAX_CHILDREN_NUM);
parent = nullptr;
is_leaf = false;
key_num = 0;
}
};
class BTree {
public:
BTree();
~BTree();
void insert(int key); // 插入关键字
void remove(int key); // 删除关键字
bool search(int key); // 查找关键字
void print_tree(); // 输出B树的结构
private:
BTreeNode* root; // 指向B树根节点的指针
void split_child(BTreeNode* parent, int pos, BTreeNode* child); // 分裂子节点
void merge_child(BTreeNode* parent, int pos, BTreeNode* child); // 合并子节点
void borrow_from_left(BTreeNode* parent, int pos, BTreeNode* child); // 从左兄弟节点中借关键字
void borrow_from_right(BTreeNode* parent, int pos, BTreeNode* child); // 从右兄弟节点中借关键字
void insert_nonfull(BTreeNode* node, int key); // 在非满节点中插入关键字
void remove_nonleaf(BTreeNode* node, int key); // 在非叶子节点中删除关键字
void remove_leaf(BTreeNode* node, int key); // 在叶子节点中删除关键字
BTreeNode* search_node(int key); // 查找包含关键字的节点
void print_node(BTreeNode* node); // 输出节点信息
void destroy_tree(BTreeNode* node); // 销毁B树
};
BTree::BTree() {
root = nullptr;
}
BTree::~BTree() {
destroy_tree(root);
}
void BTree::insert(int key) {
if (root == nullptr) {
root = new BTreeNode();
root->keys[0] = key;
root->is_leaf = true;
root->key_num = 1;
}
else {
if (root->key_num == MAX_KEY_NUM) {
BTreeNode* new_root = new BTreeNode();
new_root->children[0] = root;
new_root->parent = nullptr;
root->parent = new_root;
split_child(new_root, 0, root);
root = new_root;
}
insert_nonfull(root, key);
}
}
void BTree::remove(int key) {
if (root == nullptr) {
cout << "BTree is empty!" << endl;
return;
}
remove_nonleaf(root, key);
}
bool BTree::search(int key) {
return (search_node(key) != nullptr);
}
void BTree::split_child(BTreeNode* parent, int pos, BTreeNode* child) {
BTreeNode* new_child = new BTreeNode();
new_child->is_leaf = child->is_leaf;
new_child->key_num = MIN_KEY_NUM;
for (int i = 0; i < MIN_KEY_NUM; i++) {
new_child->keys[i] = child->keys[i + MIN_CHILDREN_NUM];
}
if (!child->is_leaf) {
for (int i = 0; i < MIN_CHILDREN_NUM; i++) {
new_child->children[i] = child->children[i + MIN_CHILDREN_NUM];
new_child->children[i]->parent = new_child;
}
}
child->key_num = MIN_KEY_NUM;
for (int i = parent->key_num; i > pos; i--) {
parent->children[i + 1] = parent->children[i];
parent->children[i + 1]->parent = parent;
}
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] = child->keys[MIN_KEY_NUM];
parent->key_num++;
}
void BTree::merge_child(BTreeNode* parent, int pos, BTreeNode* child) {
BTreeNode* left_child = parent->children[pos];
left_child->keys[MIN_KEY_NUM] = parent->keys[pos];
left_child->key_num++;
for (int i = 0; i < MIN_KEY_NUM; i++) {
left_child->keys[MIN_KEY_NUM + 1 + i] = child->keys[i];
left_child->key_num++;
}
if (!child->is_leaf) {
for (int i = 0; i < MIN_CHILDREN_NUM; i++) {
left_child->children[MIN_CHILDREN_NUM + i] = child->children[i];
left_child->children[MIN_CHILDREN_NUM + i]->parent = left_child;
}
}
for (int i = pos; i < parent->key_num - 1; i++) {
parent->keys[i] = parent->keys[i + 1];
parent->children[i + 1] = parent->children[i + 2];
parent->children[i + 1]->parent = parent;
}
parent->key_num--;
delete child;
}
void BTree::borrow_from_left(BTreeNode* parent, int pos, BTreeNode* child) {
BTreeNode* left_child = parent->children[pos - 1];
child->key_num++;
for (int i = child->key_num - 1; i > 0; i--) {
child->keys[i] = child->keys[i - 1];
}
if (!child->is_leaf) {
for (int i = child->key_num; i > 0; i--) {
child->children[i] = child->children[i - 1];
child->children[i]->parent = child;
}
child->children[0] = left_child->children[left_child->key_num];
child->children[0]->parent = child;
}
child->keys[0] = parent->keys[pos - 1];
parent->keys[pos - 1] = left_child->keys[left_child->key_num--;]}
void BTree::borrow_from_right(BTreeNode* parent, int pos, BTreeNode* child) {
BTreeNode* right_child = parent->children[pos + 1];
child->keys[child->key_num] = parent->keys[pos];
child->key_num++;
if (!child->is_leaf) {
child->children[child->key_num] = right_child->children[0];
child->children[child->key_num]->parent = child;
}
parent->keys[pos] = right_child->keys[0];
right_child->key_num--;
for (int i = 0; i < right_child->key_num; i++) {
right_child->keys[i] = right_child->keys[i + 1];
}
if (!right_child->is_leaf) {
for (int i = 0; i < right_child->key_num + 1; i++) {
right_child->children[i] = right_child->children[i + 1];
right_child->children[i]->parent = right_child;
}
}
}
BTreeNode* BTree::insert_node(BTreeNode* 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++;
BTreeNode* 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 BTree::insert(int key) {
if (root == nullptr) {
root = new BTreeNode();
root->is_leaf = true;
root->keys[0] = key;
root->key_num = 1;
} else {
if (root->key_num == MAX_KEY_NUM) {
BTreeNode* new_root = new BTreeNode();
new_root->is_leaf = false;
new_root->key_num = 0;
new_root->children[0] = root;
root->parent = new_root;
split_child(new_root, 0, root);
insert_node(new_root, key);
root = new_root;
} else {
insert_node(root, key);
}
}
}
BTreeNode* BTree::search_node(int key) {
if (root == nullptr) {
return nullptr;
} else {
BTreeNode* node = root;
while (node != nullptr) {
int pos = 0;
while (pos < node->key_num && key > node->keys[pos]) {
pos++;
}
if (pos < node->key_num && key == node->keys[pos]) {
return node;
}
if (node->is_leaf) {
return nullptr;
} else {
node = node->children[pos];
}
}
return nullptr;
}
}
虽然看上去很复杂,其实学习一下对数据结构会增加认识,也可以提升代码能力。
(只是写出来大致思路,具体还有不是缺点,请见谅)
更多推荐
已为社区贡献4条内容
所有评论(0)