当前位置: 首页 > news >正文

B 树的简单认识

理解 B 树的概念

B 树是一种自平衡的查找树,能够保持数据有序。这种数据结构能够让查找数据、顺序访问、插入数据及删除数据的动作,都能在对数时间内完成。

同一般的二叉查找树不同,B 树是一棵多路平衡查找树,其特性是:结点的孩子结点数可以多于两个,且每一个结点处可以存储多个元素。

在 B 树中,非叶子结点可以拥有可变数量的子结点,为了维持在预先设定的数量范围内,通常是对非叶子结点进行合并和分离。其优势是不需要像其他自平衡查找树那样频繁地重新保持平衡,其劣势是结点未被完全填充时会浪费一些空间。

特性

通常,我们会在 B 树的名称前添加阶数以示说明,如 m 阶 B 树。一个 m 阶的 B 树具有以下特性:

  • 任意结点最多有 m 个孩子结点
  • 任意除根结点以外的非叶子结点最少有 m2 个子结点
  • 如果根结点不是叶子结点,那么它至少有 2 个孩子结点
  • 有 k 个孩子结点的非叶子结点有 k-1 个键
  • 所有的叶子结点都在同一层,B 树也是通过此约束来保持树的平衡

下述展示的是一个 3 阶 B 树:

变体

B 树可以指一个特定的树形结构,也可以指大体上的一类树形结构。

对于 B 树这一类树形结构,还包括了 B+ 树和 B* 树等结构,它们的简单定义如下:

对于 B+ 树,关键字只存储在叶子结点,非叶子结点存储的是叶子结点所存储关键字的部分拷贝,所有的叶子结点也都在相同的高度,叶子结点本身按关键字大小从小到大链接。

B* 树是 B+ 树的变体,在 B+ 树的基础上,非叶子结点(除根结点外)会增加指向同一层兄弟的指针,且非叶子结点关键字个数至少为 2m3,即块的最低使用率为 23(B+ 树为 12)。

下面为 B* 树的结构:

起源和运用

其实,B 树就是一种为磁盘而设计的树形结构,主要是降低其他树形结构访问磁盘的 IO 次数。

磁盘读取

从磁盘读取数据的时间主要涉及到“寻道时间”和“旋转延迟”:

  • 寻道时间指的是磁盘接收到系统指令后,磁头从头开始移动到数据所在磁道所需要的时间,可能是 0 到 20 毫秒甚至更久
  • 旋转延迟指的是寻道结束后,磁盘将对应的扇区旋转到磁头下所需要的时间,其平均时间大约在旋转周期的 50% 左右,对于一个 7200 转的磁盘,采用 60×1000÷7200 的公式计算得知一次旋转周期事件为 8.33 毫秒左右

磁盘的顺序读写会比随机读写快也是这个原因,在顺序读写时,磁头不需要再做寻道,仅需很少的旋转时间,而随机读写则需要不停地移动磁头寻找对应的磁道。

磁盘预读

为了尽量减少 IO 操作,计算机系统一般采取预读的方式,预读的长度一般为页(Page)的整数倍。

页是计算机管理存储器的逻辑块,硬件及操作系统往往将主存和磁盘存储区分割为连续的大小相等的块,每个存储块称为一页(多数操作系统页的大小为 4k),主存和磁盘以页为单位交换数据。

计算机系统是分页读取和存储的,每次读取和存取的最小单元为一页,而磁盘预读时通常会读取页的整数倍。

索引结构

对于文件系统和数据库系统的索引,通常以文件的形式存储在磁盘上,因此查找索引也会执行磁盘 IO 操作,如果查找过程中磁盘 IO 的存取次数过多会影响索引的效率。

数据库系统普遍使用 B 树或者 B+ 树作为索引结构,其巧妙地利用了磁盘预读原理,将一个结点设置为一个页的大小,这样每个结点只需要一次 IO 就可以完全载入。

同时,在使用过程中还运用了以下技巧:

  • 每次新建结点时,直接申请一个页的空间,实现一个结点只需一次 IO
  • 将根结点常驻内存,在实际使用时可以减少 1 次 IO

使用 B 树作为索引结构时,由于结点的大小等于一个页的大小,通常阶会比较大,因此树的深度较浅(通常不超过 3),查找效率非常高。

缺点

虽然数据库系统普遍使用 B 树作为索引结构,但是仍然有以下缺点:

  • 非叶子结点直接存储数据,同一结点存储的索引数会比较少
  • 数据即可能存储在叶子结点,也可能存储在非叶子结点,查询效率相对不稳定
  • 在同层结点之间没有指针相邻,不适合做一些数据遍历操作

插入和删除

插入

B 树所有的插入过程都以根结点起始,首先是要查找到新元素所要存储的结点,然后判断插入结点的元素数量:

  1. 如果结点存储的元素数量小于最大值,那么有空间容纳新的元素,直接插入并保持结点内部有序即可;
  2. 如果结点存储的元素数量大于等于最大值,将它平均地分裂成 2 个结点:
    1. 从该结点的原有元素和新的元素中选择出中位数(按顺序排列的一组数据中居于中间位置的数);
    2. 小于中位数的元素放入左边结点,大于中位数的元素放入右边结点,中位数作为分隔值;
    3. 将分隔值插入到父结点中,这也可能会造成父结点发生分裂,父结点的分裂也可能会造成它的父结点分裂,以此类推;如果没有父结点,就创建一个新的父结点。

删除

删除 B 树中的结点有两种常用的策略:

  • 定位并删除元素,然后调整树使它满足约束条件
  • 从上到下处理这棵树,在进入一个结点之前,调整树使得其之后一旦遇到要删除的键,可以被直接删除而不需要再进行调整

对于前一种删除策略,其删除流程如下:

  1. 如果删除叶子结点中的元素,将它直接删除,如果结点中的元素数量小于最小值,则进行重新平衡操作;
  2. 如果删除非叶子结点中的元素,选择一个新的分隔值(左子树中最大的元素或右子树中最小的元素),将它从叶子结点中移除,替换掉被删除的元素作为新的分隔值,如果该叶子结点中的元素数量小于最小值,则进行重新平衡操作;
  3. 重新平衡操作从叶子结点开始,向根结点进行,直到树重新平衡。

在删除结点中,使 B 树重新平衡主要会有以下情况:

  1. 如果缺少元素结点的右兄弟结点存在且拥有多余的元素,那么向左旋转:
    1. 将父结点的分隔值移动到左子树中最大元素处;
    2. 将右兄弟结点的最小元素移动到原父结点的分隔值处;
  2. 如果缺少元素结点的左兄弟结点存在且拥有多余的元素,那么向右旋转:
    3. 将父结点的分隔值移动到右子树中最小元素处;
    4. 将左兄弟结点的最大元素移动到原父结点的分隔值处;
  3. 如果缺少元素结点的两个直接兄弟结点都只有最小数量的元素,那么将它与左兄弟结点以及它们在父结点中的分隔值合并:
    5. 将分隔值复制到左边的结点;
    6. 将此缺少元素结点中的所有元素移动到左边结点;
    7. 将缺少元素的结点移除;
    8. 如果父结点是根结点且没有元素,则释放它并让合并后的结点成为新的根结点;如果父结点的元素数量小于最小值,重新平衡父结点。

对 B 树做删除元素的操作比较复杂,但仍然是以保持 B 树平衡为主,并且不使其导致特性失效。

相关文章:

B 树的简单认识

理解 B 树的概念 B 树是一种自平衡的查找树,能够保持数据有序。这种数据结构能够让查找数据、顺序访问、插入数据及删除数据的动作,都能在对数时间内完成。 同一般的二叉查找树不同,B 树是一棵多路平衡查找树,其特性是&#xff…...

【大数据Hive3.x数仓开发】窗口函数案例:连续N次登录的用户;级联累加求和;分组TopN

文章目录1 统计连续N次登录的用户(N>2)自连接过滤实现窗口函数lead()实现2 级联累加求和自连接窗口函数sum()实现3 分组TopN问题对窗口函数的讲解part见:【大数据Hive3.x数仓开发】函数–窗口函数 1 统计连续N次登录的用户(N&…...

openpyxl库自动填充excel实例分享

openpyxl可以通过编写Python脚本实现自动化Excel操作,包括自动填充数据、格式化单元格、生成图表等操作。 以下是一个常见的自动化Excel操作示例: 自动填充数据: from openpyxl import Workbook from openpyxl.utils import get_column_l…...

ICLR2021清华团队做的知识蒸馏提升detector的点的工作paper 小陈读论文系列

这个作者栏目就是一个词 清爽 牛逼不需要花里胡哨哈哈 无疑是有点tian了哈哈 不重要 毕竟有机会研读 梦中情笑的paper 还是很感激的 真的 很清爽啊 很多KD的工作确实 在下游任务呢效果不是很好 然后就引出了自己的关于提升知识蒸馏在OD方面的工作 OD 首先就有两个问题 1.前…...

Java核心技术知识点笔记—集合框架

前言:Java最初版本只为最常用的数据结构提供了很少的一组类:Vector、Stack、Hashtable、BitSet和Enumeration接口。其中,Enumeration接口提供了一种用于访问任意容器中各个元素的抽象机制。与现代数据结构类库常见情况一样,Java集…...

Rsync数据同步工具

一、什么是Rsync Rsync是一款开源的,快速的,多功能的,可实现全量及增量(差异化备份)的本地或远程数据同步备份的优秀工具。 Rsync软件适用于Unix、Linux、Windows等多种操作系统。 (1)可使本地…...

redux小结

store.dispatch(action对象) 在 dispatch 中调用 action 方法返回 action 对象 // /actions/index.js /*** Action:* action本质上是一个 JS 对象;* 必须要包含 type 属性,否则会报错;* 只描述了有事情要发生&#xff0c…...

【Python】【进阶篇】十、Pygame的Font文本和字体

目录十、Pygame的Font文本和字体10.1 font.SysFont()10.2 font.Font()10.3 字体对象方法十、Pygame的Font文本和字体 Pygame 通过pygame.font模块来创建一个字体对象,从而实现绘制文本的目的。 该模块的常用方法如下所示: 名称说明pygame.font.init()初…...

【从零开始学习 UVM】10.8、UVM TLM —— UVM TLM Example

文章目录 subComp1subComp2ComponentAsubComp3ComponentBTop Env/Test这个 UVM TLM 示例使用之前文章中讨论的 put 端口、TLM FIFO 和 get 端口来构建一个具有不同层次的 TLM 端口的测试台。 下面定义了一个名为Packet的类,作为从一个组件传输到另一个组件的数据项。这个类对象…...

获取自己所上传资源的下载量

import requestsurl = https://download-console-api.csdn.net/v1/user/sources/getUploadListByUserName?status=2&pageNum=1&pageSize=100 cookie = # 这里填自己的cookie header = {"authority": "download-console-api.csdn.net","met…...

Aspose.cells模板导出使用记录

简述 用Aspose.cells导出可以方便地将数据到Excel文档中,简单的直接将DataTable列表写入即可,复杂的格式一般会先做好模板,再将数据填充进去,这样可以保持设置好的样式,又能快速填充内容,十分方便。 智能…...

AcWing——糖果传递

有 n个小朋友坐成一圈,每人有 a[i]个糖果。 每人只能给左右两人传递糖果。 每人每次传递一个糖果代价为 1。 求使所有人获得均等糖果的最小代价。 输入格式 第一行输入一个正整数 n,表示小朋友的个数。 接下来 n 行,每行一个整数 a[i]&…...

Redis中的单线程模型

文章目录 文件事件处理器模型Redis的客户端与服务端的交互过程图Redis基于Reactor模式开发了自己的网络事件处理器,称之为 文件事件处理器(File Event Hanlder)。 文件事件处理器由Socket、IO多路复用程序文件事件分派器(dispather)事件处理器(handler)文件事件处理器模型 IO…...

Python函数默认参数设置(超级详细)

我们知道,在调用函数时如果不指定某个参数,Python 解释器会抛出异常。为了解决这个问题,Python 允许为参数设置默认值,即在定义函数时,直接给形式参数指定一个默认值。这样的话,即便调用函数时没有给拥有默…...

人工智能如何赋能业务创新?安克创新有话要说

对于一家企业来说,应该如何运用人工智能技术助力业务创新?作为一家多年复合增长率超过35%的企业,安克创新对这个话题无疑有着深切的体验感悟。飞速成长的消费电子企业众所周知,当下各行各业都在如火如荼地开展人工智能应用&#x…...

如何学习与学习的本质

如何学习两种模式两种记忆方式拖延问题学习方法学习本质两种模式 专注模式发散模式 专注模式和发散模式可以进行切换,提高效率, 发散模式可以后台工作。 两种记忆方式 工作记忆(前额叶皮质)长时记忆(图像比较容易记…...

C++ deque容器

C deque容器 文章目录C deque容器前言1. deque容器基本概念2. deque构造函数3. deque赋值操作4. deque大小操作5. deque 插入和删除6. deque 数据存取7. deque 排序总结前言 本文包含deque容器基本概念、deque构造函数、deque赋值操作、deque大小操作、deque插入和删除、deque…...

HashMap的底层原理

hashmap是一个以key,value形式存储的集合,在JDK1.7中是以数组链表的数据结构,在JDK1.8中是数组链表红黑树的数据结构,他在对数据操作时继承了数组的线性查找和链表的寻址修改 hashmap是线程不安全的 : 在JDK1.7中会造成环形链和数据丢失的情况 在JDK1.8中hashmap的put过程会造…...

Django 4.0文档学习(四)

上篇文章 Django 4.0文档学习(四) 文章目录编写你的第一个 Django 应用,第 6 部分自定义应用的界面和风格编写你的第一个 Django 应用,第 7 部分自定义后台表单自定义后台更改列表自定义后台界面和风格自定义后台主页编写你的第一…...

2023年全国最新高校辅导员精选真题及答案38

百分百题库提供高校辅导员考试试题、辅导员考试预测题、高校辅导员考试真题、辅导员证考试题库等,提供在线做题刷题,在线模拟考试,助你考试轻松过关。 112.为改变重知识传授轻能力培养的大学课堂,教学方法可以采用(&am…...

RestClient

什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端,它允许HTTP与Elasticsearch 集群通信,而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级&#xff…...

Python爬虫实战:研究MechanicalSoup库相关技术

一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...

从零实现富文本编辑器#5-编辑器选区模型的状态结构表达

先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...

Qt Widget类解析与代码注释

#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码,写上注释 当然可以!这段代码是 Qt …...

RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill

视觉语言模型(Vision-Language Models, VLMs),为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展,机器人仍难以胜任复杂的长时程任务(如家具装配),主要受限于人…...

【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制

使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下,限制某个 IP 的访问频率是非常重要的,可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案,使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...

腾讯云V3签名

想要接入腾讯云的Api,必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口,但总是卡在签名这一步,最后放弃选择SDK,这次终于自己代码实现。 可能腾讯云翻新了接口文档,现在阅读起来,清晰了很多&…...

【 java 虚拟机知识 第一篇 】

目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...

在golang中如何将已安装的依赖降级处理,比如:将 go-ansible/v2@v2.2.0 更换为 go-ansible/@v1.1.7

在 Go 项目中降级 go-ansible 从 v2.2.0 到 v1.1.7 具体步骤: 第一步: 修改 go.mod 文件 // 原 v2 版本声明 require github.com/apenella/go-ansible/v2 v2.2.0 替换为: // 改为 v…...

密码学基础——SM4算法

博客主页:christine-rr-CSDN博客 ​​​​专栏主页:密码学 📌 【今日更新】📌 对称密码算法——SM4 目录 一、国密SM系列算法概述 二、SM4算法 2.1算法背景 2.2算法特点 2.3 基本部件 2.3.1 S盒 2.3.2 非线性变换 ​编辑…...