B树,B+树,B*树

下面我们来详细讲解一下 B树、B+树、B*树 这三种非常重要的多路平衡查找树。它们在数据库和文件系统中有着极其广泛的应用。


一、为什么需要这些树结构?

在开始之前,我们先思考一个问题:为什么已经有了二叉搜索树(BST)、AVL树、红黑树,还需要B树家族?

答案是:磁盘I/O

  • 内存访问:速度极快,纳秒级别。
  • 磁盘访问:速度极慢,毫秒级别,比内存慢了几个数量级。

操作系统从磁盘读取数据时,并不是按需一个字节一个字节地读,而是以(Page,通常为4KB或8KB)为单位进行预读。一次I/O操作会把一整页的数据都加载到内存中。

传统的二叉树(如红黑树)虽然内存中效率很高,但每个节点只存储少量数据,如果数据量巨大,树会变得很高。查询一个数据可能需要从根节点访问到叶子节点,这期间可能发生很多次磁盘I/O(因为节点可能不在同一页),性能会急剧下降。

B树家族的设计目标就是为了减少磁盘I/O次数。它们的核心思想是:

一个节点 = 一个磁盘页

通过在每个节点中存储更多的键和指针,让树变得更“矮胖”,从而降低树的高度,减少查询时的I/O次数。


二、B树 (B-Tree)

B树是一种自平衡的多路搜索树,它不是二叉的,一个节点可以有多个子节点。

1. 结构特点
  • 平衡性:所有叶子节点都位于同一层,保证了查询性能的稳定。
  • 多路性:一个节点可以拥有多于两个的子节点。这通常用“阶”(m)来定义。一棵m阶的B树满足以下条件:
    • 每个节点最多有 m 个子节点。
    • 除根节点和叶子节点外,每个节点至少有 ceil(m/2) 个子节点(ceil是向上取整)。
    • 根节点至少有2个子节点(除非它同时也是叶子节点)。
    • 所有叶子节点都在同一层。
    • 一个有 k 个子节点的非叶子节点,包含 k-1 个键(Key)。
    • 节点中的键是有序的。
2. 节点结构

一个典型的B树节点包含:

  • n 个键 K₁, K₂, ..., Kₙ
  • n+1 个指针 P₀, P₁, ..., Pₙ
  • 指针指向子节点,键和指针的排列满足:P₀指向的子树中所有键 < K₁ < P₁指向的子树中所有键 < K₂ < … < Kₙ < Pₙ指向的子树中所有键。

示例(3阶B树,也叫2-3树):

        [ 20 | 40 ]/     |     \[10, 15] [30, 35] [50, 60]
  • 每个节点最多有3个子节点,至少有2个子节点。
  • 每个节点最多有2个键,至少有1个键。
3. 操作
  • 查找:从根节点开始,将待查找的键与节点中的键比较,确定下一步要进入哪个子树,直到找到或到达叶子节点。
  • 插入:找到合适的叶子节点插入。如果插入后节点键的数量超过 m-1,则节点分裂。中间的键向上提升到父节点,如果父节点也满了,则继续向上分裂,可能一直到根节点。
  • 删除:比较复杂,可能需要从兄弟节点“借”键,或者与兄弟节点合并,甚至可能导致父节点的合并,是一个递归的过程。
4. 优缺点
  • 优点
    • 矮胖,树的高度低,I/O次数少,非常适合磁盘存储。
    • 查询、插入、删除的时间复杂度都为 O(logₘN),其中N是键的数量,m是阶数。
  • 缺点
    • 每个节点都存储了键和数据(如果数据很大,节点能存的键就变少了,树会变高)。
    • 范围查询效率不高,因为数据分散在所有节点中,需要进行中序遍历,这会涉及大量的随机I/O。

三、B+树 (B+ Tree)

B+树是B树的变种,也是目前数据库索引中最常用的数据结构(如MySQL的InnoDB引擎)。它对B树做了优化,使其更适合范围查询和全表扫描。

1. 结构特点(与B树的区别)

B+树在B树的基础上增加了以下特性:

  • 数据只在叶子节点
    • 非叶子节点(索引节点):只存储键和指向子节点的指针,不存储数据。这使得非叶子节点可以存储更多的键,树的结构更“矮胖”,I/O效率更高。
    • 叶子节点(数据节点):存储了所有的键和对应的数据。
  • 叶子节点形成有序链表
    • 所有的叶子节点通过指针连接成一个双向有序链表
    • 这使得范围查询变得极其高效,只需定位到范围的起始点,然后沿着链表顺序遍历即可,几乎都是顺序I/O。
  • 查询效率更稳定
    • 任何查询都必须从根节点走到叶子节点才能获取到数据。而B树可能在非叶子节点就命中数据。这使得B+树的每次查询的I/O次数更加稳定。
2. 图示
        [ 20 | 40 ]/     |     \[ 10 ]   [ 30 ]   [ 50 ]/         |         \
[10, Data] [30, Data] [50, Data]<--------> <--------> <--------> (双向链表)
  • 上面的非叶子节点只做索引,不存数据。
  • 下面的叶子节点存数据,并且用链表连接。
3. 优缺点
  • 优点
    • 更矮胖:由于非叶子节点不存数据,能容纳更多键,树高更低,I/O次数更少。
    • 查询性能稳定:每次查询都必须查到叶子节点,性能稳定。
    • 范围查询极其高效:叶子节点的有序链表结构,使得范围查询和排序操作非常快。
    • 全表扫描快:只需遍历叶子节点的链表即可。
  • 缺点
    • 单点查询(根据主键查一条记录)可能比B树稍慢,因为B树可能在非叶子节点就找到数据,而B+树必须走到叶子节点。但在实际应用中,由于B+树更矮胖,这个劣势通常不明显,甚至可能更快。

四、B*树 (B* Tree)

B*树是B树的另一个变种,它的目标是进一步提高节点的空间利用率

1. 结构特点(与B树的区别)

B*树的核心思想是增加节点的填充率,从而减少节点分裂的频率。

  • 更高的填充因子
    • B树要求每个非根、非叶节点至少半满(ceil(m/2))。
    • B*树要求每个非根、非叶节点至少 2/3满ceil(2m/3))。
  • 独特的分裂策略
    • 当一个节点满了需要插入新数据时,B*树不会立即分裂
    • 它会先检查其相邻的兄弟节点是否还有空间。
    • 如果兄弟节点未满:将当前节点和兄弟节点的键重新分配,让两个节点都达到2/3满。这个过程称为节点重分配
    • 如果兄弟节点也满了:才会进行分裂。但B*树的分裂也与B树不同。它不是将一个节点分成两个,而是将当前节点和它的一个兄弟节点一起分裂成三个节点,并保证这三个节点都是2/3满的。
2. 优缺点
  • 优点
    • 极高的空间利用率:由于2/3的填充因子和延迟分裂策略,节点的空间利用率非常高,浪费的空间很少。
    • 更少的分裂操作:节点重分配和“分裂成三”的策略大大降低了节点分裂的频率,从而减少了I/O操作,提高了插入性能。
  • 缺点
    • 实现复杂:插入和删除的逻辑比B树和B+树复杂得多,需要处理节点重分配和复杂的分裂逻辑。
    • 应用较少:由于其复杂性,B*树在实际应用中不如B+树普及。但在一些对空间利用率和插入性能要求极高的文件系统中,可能会看到它的身影。

总结与对比

特性B树B+树B*树
数据存储位置所有节点(键+数据)仅叶子节点(键+数据)仅叶子节点(键+数据)
非叶子节点作用索引+数据仅索引仅索引
叶子节点结构独立,无连接双向有序链表双向有序链表
查询性能不稳定(可能在非叶子节点命中)稳定(必须到叶子节点)稳定(必须到叶子节点)
范围查询效率低(中序遍历,随机I/O)效率极高(链表顺序遍历)效率极高(链表顺序遍历)
节点填充率至少半满 (ceil(m/2))至少半满 (ceil(m/2))至少2/3满 (ceil(2m/3))
分裂策略节点满则分裂成两个节点满则分裂成两个先尝试与兄弟节点重分配,失败则分裂成三个
空间利用率一般较高非常高
实现复杂度中等中等
主要应用文件系统(如HFS+, NTFS部分)数据库索引(MySQL, Oracle)少数文件系统,对空间利用率要求高的场景

一句话总结

  • B树:是“矮胖”的多路树,解决了磁盘I/O问题,但数据分散,不适合范围查询。
  • B+树:在B树基础上,将数据全部移到叶子节点并用链表连接,完美优化了范围查询,成为数据库索引的事实标准
  • B*树:在B树基础上,通过提高填充率和改进分裂策略,极致地优化了空间利用率和插入性能,但实现复杂,应用较少。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/96854.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/96854.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

汽车零部件工厂ESOP系统工业一体机如何选型

在汽车零部件工厂的生产管理中&#xff0c;ESOP 系统发挥着至关重要的作用。而工业一体机作为 ESOP 系统的关键硬件支撑&#xff0c;其选型的合理性直接关系到生产效率的提升、生产过程的精准控制以及生产数据的可靠采集与分析。因此&#xff0c;为汽车零部件工厂选择一款适合的…

​维基框架 (Wiki Framework) 1.1.0 版本发布​ 提供多模型AI辅助开发

介绍 多模型AI辅助开发​ 维基框架1.1.0集成了主流AI引擎的统一接口&#xff0c;支持开发者按需调用不同模型的优势能力&#xff1a; ​DeepSeek​&#xff1a;专注代码生成与重构&#xff0c;擅长复杂业务逻辑实现 ​ChatGPT​&#xff1a;多模态推理能力&#xff0c;适用于…

LabVIEW调用MATLAB 的分形生成

LabVIEW 调用 MATLAB&#xff0c;可借前者可视化流程与硬件交互优势&#xff0c;结合后者强数值计算、算法能力&#xff0c;复用成熟算法提速开发&#xff0c;还能灵活改代码。但需匹配版本、装运行环境&#xff0c;数据传递有性能损耗&#xff0c;脚本出错需跨软件调试。​优点…

ubuntu20.04开发ros2,使用docker安装部署的详细教程

学习docker的教程&#xff1a;可以直接在菜鸟教程上学习即可阶段 0&#xff1a;系统检查| 内容 | 建议 | |------|------| | 操作系统 | Ubuntu 22.04&#xff08;与 ROS2 Humble 最匹配&#xff09; | | 用户权限 | 能执行 sudo |&#x1f9e9; 阶段 1&#xff1a;在 Ubuntu 上…

SQL Server缩小日志文件.ldf的方法(适用于开发环境)

SQL Server缩小日志文件.ldf的方法&#xff08;适用于开发环境&#xff09; 核心概念&#xff1a;为什么日志文件会变大&#xff1f; 首先&#xff0c;理解原因至关重要。事务日志文件在以下情况下会增长&#xff1a; 大量操作&#xff1a;执行了大批量插入、更新或删除操作&am…

2.3零基础玩转uni-app轮播图:从入门到精通 (咸虾米总结)

还在uni-app中的轮播图组件头疼吗&#xff1f;看完这篇&#xff0c;让你轻松掌握swiper的所有秘密&#xff01;轮播图的重要性 在现代移动应用开发中&#xff0c;轮播图&#xff08;Swiper&#xff09;已成为展示焦点内容、广告推广和产品展示的首选组件。无论是电商平台的商品…

FPGA学习笔记——AHT20温湿度读取并在串口显示(IIC协议)

目录 一、任务 二、分析 1.需要了解的 2.需要用到的模块 3.流程分析 三、Visio图 四、代码 五、实验现象 一、任务 使用IIC协议通信的AHT20&#xff0c;将温湿度数据读取出来&#xff0c;并在串口助手上显示。 二、分析 1.需要了解的 需要了解IIC协议简介 也可以看看E…

Pycharm SSH连接

添加远程服务器文件——>设置——>项目下的Python解释器——>添加解释器——>SSH在弹出的弹窗中&#xff0c;输入远程的主机、端口和用户名、一直下一步&#xff0c;得到如下图所示的结果&#xff1a;选择Conda 环境&#xff1a;第一步选择Conda环境&#xff1b;第…

c# 读取xml文件内的数据

好多大型的项目&#xff0c;把一些固定的参数都存在 xml文件里。创建c# winfom 项目&#xff0c;test_xml创建resources文件夹存放xml文件创建parameters.xml文件<root><test_xml><param name "threshold" value "128"/><param name …

Legion Y7000P IRX9 DriveList

Legion Y7000P IRX9 DriveList 联想Y7000P驱动列表 驱动列表 intelwlan-TYY5057FK6MQBRF0.exe NVVGA-TYY5057F3M0H9RF0.exe RTKwlan-TYY5077FFSNECRF0.exe audio-TYY5057F4N1JARF0.exe chipset-TYY5037FB10X3RF0.exe hdr-TYY5027FXNF9AWF0.exe intelVGA-TYY5057F5R9J7RF…

编程与数学 02-017 Python 面向对象编程 23课题、测试面向对象的程序

编程与数学 02-017 Python 面向对象编程 23课题、测试面向对象的程序一、单元测试&#xff08;Unit Testing&#xff09;使用 unittest 模块使用 pytest二、集成测试&#xff08;Integration Testing&#xff09;三、模拟对象&#xff08;Mocking&#xff09;四、测试驱动开发&…

[React]Antd Cascader组件地区选择

前言表单中添加一个地区选择功能&#xff0c;要求支持增删改查功能。Cascader 使用Cascader组件动态加载地区选项。使用 loadData 实现动态加载选项&#xff0c;&#xff08;loadData 与 showSearch 无法一起使用&#xff09;。 这里使用了Form.Item组件。 <Form.Itemlabel{…

深度学习-----《PyTorch神经网络高效训练与测试:优化器对比、激活函数优化及实战技巧》

一、训练过程并行批量训练机制一次性输入64个批次数据&#xff0c;创建64个独立神经网络并行训练。所有网络共享参数&#xff08;Ω&#xff09;&#xff0c;更新时计算64个批次的平均损失&#xff0c;统一更新全局参数。梯度更新策略使用torch.no_grad()上下文管理器清理反向传…

Matplotlib 可视化大师系列(五):plt.pie() - 展示组成部分的饼图

目录Matplotlib 可视化大师系列博客总览Matplotlib 可视化大师系列&#xff08;五&#xff09;&#xff1a;plt.pie() - 展示组成部分的饼图一、 饼图是什么&#xff1f;何时使用&#xff08;何时避免&#xff09;&#xff1f;二、 函数原型与核心参数三、 从入门到精通&#x…

C++ Core Guidelines 核心理念

引言 C 是一门功能强大但复杂性极高的编程语言。为了帮助开发者更高效、安全地使用现代 C&#xff0c;C 核心指南&#xff08;CppCoreGuidelines&#xff09;应运而生。这份由 C 之父 Bjarne Stroustrup 等人主导的指南&#xff0c;提供了大量关于 C 编码的规则、最佳实践和设…

vue3 - 组件间的传值

组件间传参 父传子v-on/props 父组件使用v-on:绑定要传的参数:parentData"parentData"&#xff1a; <template><div><Child1 :parentData"parentData"></Child1></div> </template> <script setup lang"ts…

Kafka 在 6 大典型用例的落地实践架构、参数与避坑清单

一、选型速查表场景关键目标推荐清单&#xff08;示例&#xff09;消息&#xff08;Messaging&#xff09;解耦、低延迟、可靠投递acksall、enable.idempotencetrue、retries>0、min.insync.replicas2、合理分区键、DLT网站活动追踪吞吐极高、可回放主题按类型拆分&#xff…

Node.js(1)—— Node.js介绍与入门

前面我们谈到一些前端开发的内容&#xff0c;学习了HTML、css和JavaScript&#xff0c;已经掌握了如何编写一些简单功能的网页。但是只属于前端部分&#xff0c;我们只能在本地打开文件进行浏览&#xff0c;不能让其他人打开我们编写的网站&#xff1b;这时就需要后端部分上场了…

Python办公——爬虫百度翻译网页版(自制翻译小工具——进阶更新版)

目录 专栏导读 前言 项目概述 功能特点 技术栈 核心架构设计 类结构设计 界面布局设计 核心功能实现 1. 智能语言检测 2. 异步翻译处理 3. HTTP请求处理 4. 结果解析与显示 界面设计亮点 1. 响应式布局 2. 用户体验优化 3. 现代化组件 技术难点与解决方案 1. 跨线程UI更新 2. U…