0

0

C++如何实现一个B-树_C++数据结构之B-树的插入与删除操作图解

穿越時空

穿越時空

发布时间:2025-12-19 11:17:25

|

779人浏览过

|

来源于php中文网

原创

B-树是一种自平衡多路搜索树,所有叶子节点位于同一层,每个节点最多有m-1个关键字、m个子节点,非根节点至少有⌈m/2⌉−1个关键字。插入时从根开始查找插入位置,节点满则分裂,确保不溢出;删除时若关键字在内部节点,用子树最值替换,遍历中保证节点关键字数大于t−1,不足时通过借元素或合并调整。核心操作为分裂与合并,维持树的平衡性,适用于文件系统和数据库等需高效磁盘I/O的场景。

c++如何实现一个b-树_c++数据结构之b-树的插入与删除操作图解

实现B-树的关键在于理解其自平衡特性:每个节点可以包含多个关键字,并且保持所有叶子节点在同一层。B-树广泛用于文件系统和数据库中,因为它能有效减少磁盘I/O操作。下面以阶数为 m 的B-树为例(即每个节点最多有 m 个子节点,最多 m-1 个关键字),讲解C++中的插入与删除操作,并配以逻辑说明。

什么是B-树?

B-树满足以下性质:

  • 根节点至少有一个关键字,非根内部节点至少有 ⌈m/2⌉−1 个关键字。
  • 每个节点最多有 m−1 个关键字,最多 m 个子节点。
  • 所有叶子节点位于同一层,代表查找失败的位置。
  • 节点中的关键字按升序排列,子树的关键字范围由父节点分隔。

例如,一个 5 阶 B-树(m=5)的节点最多有 4 个关键字、5 个子节点,最少有 2 个关键字(非根节点)。

B-树节点结构设计

在C++中定义节点类型:

立即学习C++免费学习笔记(深入)”;

struct BTreeNode {
    bool isLeaf;
    int n; // 当前关键字数量
    std::vector keys;
    std::vector children;
BTreeNode(int t, bool leaf) : isLeaf(leaf), n(0) {
    keys.resize(2 * t - 1);
    children.resize(2 * t, nullptr);
}

};

其中 t 是最小度数(minimum degree),表示每个节点至少有 t−1 个关键字(非根节点)、t 个子节点。整个树的阶数 m = 2t。

插入操作图解与实现

插入过程从根开始,向下找到合适的叶子节点插入位置。若叶子节点已满(关键字数达到 2t−1),则需要分裂。

步骤分解:

  • 若根节点满,则创建新根,原根作为子节点,并进行分裂。
  • 递归查找插入路径,遇到满节点就提前分裂,确保后续插入不会溢出。
  • 最终将关键字插入到某个叶子节点中。

分裂节点示例:

假设 t=2(即最多3个关键字),当前叶子节点已含 [10,20,30],再插入40会导致溢出。此时将中间元素20上移至父节点,原节点拆分为 [10] 和 [30,40],返回结果如下:

     父节点
      /   \
[10]       [30,40]

C++代码片段:

void splitChild(BTreeNode* parent, int i, BTreeNode* fullChild) {
    BTreeNode* newNode = new BTreeNode(fullChild->t, fullChild->isLeaf);
    newNode->n = t - 1;
for (int j = 0; j < t - 1; j++)
    newNode->keys[j] = fullChild->keys[j + t];

if (!fullChild->isLeaf) {
    for (int j = 0; j < t; j++)
        newNode->children[j] = fullChild->children[j + t];
}

for (int j = parent->n; j > i; j--)
    parent->children[j + 1] = parent->children[j];

parent->children[i + 1] = newNode;

for (int j = parent->n - 1; j >= i; j--)
    parent->keys[j + 1] = parent->keys[j];

parent->keys[i] = fullChild->keys[t - 1];
parent->n++;

}

插入主函数需处理根节点是否满的情况:

Background Eraser
Background Eraser

AI自动删除图片背景

下载
void insertNonFull(BTreeNode* node, int key);
void insert(int key) {
    if (root->n == 2*t - 1) {
        BTreeNode* newRoot = new BTreeNode(t, false);
        newRoot->children[0] = root;
        splitChild(newRoot, 0, root);
        root = newRoot;
    }
    insertNonFull(root, key);
}

删除操作图解与实现

删除更复杂,因为必须维持B-树的平衡性。核心思想是:在遍历时保证当前节点的关键字数大于 t−1,否则通过合并或借元素来调整。

主要情况分析:

  • 被删关键字在叶子节点:直接删除;若导致节点关键字过少,则考虑从兄弟借或合并。
  • 被删关键字在内部节点
    • 左子树高度足够:用左子树最大值替换该关键字。
    • 右子树高度足够:用右子树最小值替换。
    • 都不够:合并左右子树并下移关键字。
  • 当前节点关键字太少(仅 t−1 个):尝试从兄弟借一个关键字;若兄弟也少,则与其父关键字一起合并。

举例说明:

要删除关键字 K,所在节点只剩 t−1 个元素。检查任一兄弟是否有富余(> t−1)元素:

  • 若有,将父节点的一个关键字下移,兄弟的一个关键字上提,实现“旋转”。
  • 若无,则将父节点关键字与另一个兄弟合并成一个新节点。

这样可避免中途节点太小,影响后续操作。

伪代码流程:

void remove(BTreeNode* node, int key) {
    int idx = findKey(node, key);
if (idx < node->n && node->keys[idx] == key) {
    if (node->isLeaf)
        removeFromLeaf(node, idx);
    else
        removeFromInternal(node, idx);
} else {
    if (node->isLeaf) return; // 不存在

    bool lastChild = (idx == node->n);

    if (node->children[idx]->n < t)
        fill(node, idx);

    remove(node->children[idx], key);
}

}

其中 fill() 函数负责处理子节点元素不足的问题,调用 borrowFromPrev()borrowFromNext()merge() 完成调整。

总结

B-树的插入与删除本质上是对多路平衡搜索树的动态维护。关键点包括:

  • 插入时采用“向上分裂”策略,防止溢出。
  • 删除时采用“向下填充”机制,保证节点不欠元素。
  • 分裂与合并操作是核心辅助手段。

虽然实现较AVL或红黑树复杂,但B-树在大规模数据存储场景下具有显著优势——层数极低,访问效率高。

基本上就这些。掌握好分裂、合并、借元素三种技巧,就能完整实现B-树的增删逻辑。

相关专题

更多
treenode的用法
treenode的用法

​在计算机编程领域,TreeNode是一种常见的数据结构,通常用于构建树形结构。在不同的编程语言中,TreeNode可能有不同的实现方式和用法,通常用于表示树的节点信息。更多关于treenode相关问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

536

2023.12.01

C++ 高效算法与数据结构
C++ 高效算法与数据结构

本专题讲解 C++ 中常用算法与数据结构的实现与优化,涵盖排序算法(快速排序、归并排序)、查找算法、图算法、动态规划、贪心算法等,并结合实际案例分析如何选择最优算法来提高程序效率。通过深入理解数据结构(链表、树、堆、哈希表等),帮助开发者提升 在复杂应用中的算法设计与性能优化能力。

17

2025.12.22

深入理解算法:高效算法与数据结构专题
深入理解算法:高效算法与数据结构专题

本专题专注于算法与数据结构的核心概念,适合想深入理解并提升编程能力的开发者。专题内容包括常见数据结构的实现与应用,如数组、链表、栈、队列、哈希表、树、图等;以及高效的排序算法、搜索算法、动态规划等经典算法。通过详细的讲解与复杂度分析,帮助开发者不仅能熟练运用这些基础知识,还能在实际编程中优化性能,提高代码的执行效率。本专题适合准备面试的开发者,也适合希望提高算法思维的编程爱好者。

22

2026.01.06

数据库三范式
数据库三范式

数据库三范式是一种设计规范,用于规范化关系型数据库中的数据结构,它通过消除冗余数据、提高数据库性能和数据一致性,提供了一种有效的数据库设计方法。本专题提供数据库三范式相关的文章、下载和课程。

352

2023.06.29

如何删除数据库
如何删除数据库

删除数据库是指在MySQL中完全移除一个数据库及其所包含的所有数据和结构,作用包括:1、释放存储空间;2、确保数据的安全性;3、提高数据库的整体性能,加速查询和操作的执行速度。尽管删除数据库具有一些好处,但在执行任何删除操作之前,务必谨慎操作,并备份重要的数据。删除数据库将永久性地删除所有相关数据和结构,无法回滚。

2075

2023.08.14

vb怎么连接数据库
vb怎么连接数据库

在VB中,连接数据库通常使用ADO(ActiveX 数据对象)或 DAO(Data Access Objects)这两个技术来实现:1、引入ADO库;2、创建ADO连接对象;3、配置连接字符串;4、打开连接;5、执行SQL语句;6、处理查询结果;7、关闭连接即可。

347

2023.08.31

MySQL恢复数据库
MySQL恢复数据库

MySQL恢复数据库的方法有使用物理备份恢复、使用逻辑备份恢复、使用二进制日志恢复和使用数据库复制进行恢复等。本专题为大家提供MySQL数据库相关的文章、下载、课程内容,供大家免费下载体验。

255

2023.09.05

vb中怎么连接access数据库
vb中怎么连接access数据库

vb中连接access数据库的步骤包括引用必要的命名空间、创建连接字符串、创建连接对象、打开连接、执行SQL语句和关闭连接。本专题为大家提供连接access数据库相关的文章、下载、课程内容,供大家免费下载体验。

324

2023.10.09

菜鸟裹裹入口以及教程汇总
菜鸟裹裹入口以及教程汇总

本专题整合了菜鸟裹裹入口地址及教程分享,阅读专题下面的文章了解更多详细内容。

0

2026.01.22

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
HTML5/CSS3/JavaScript/ES6入门课程
HTML5/CSS3/JavaScript/ES6入门课程

共102课时 | 6.8万人学习

前端基础到实战(HTML5+CSS3+ES6+NPM)
前端基础到实战(HTML5+CSS3+ES6+NPM)

共162课时 | 19万人学习

第二十二期_前端开发
第二十二期_前端开发

共119课时 | 12.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号