B树和B+树MySQL为什么用B+树?

news2024/12/28 8:15:11

文章目录

  • B树和B+树
    • B树
      • B树的定义
      • B树的插入操作
      • 删除操作
    • B+树
      • B+树的定义
      • B+树的插入操作
      • 删除操作
  • B树和B+树的区别?
  • MySQL数据库为啥用B+树作为索引,而不用B树?

B树和B+树

原文链接:https://blog.csdn.net/jinking01/article/details/115130286

B树

B树的定义

B树也称为B-树,是一颗多路平衡查找树。描述B树的时候需要确定它的阶数,阶数表示一个节点最多可以有几个孩子,一般用m表示。当m=2时,就是二叉搜索树。

对于m阶B树定义如下:

  1. 每个结点最多有m-1个关键字。
  2. 根结点可以只有一个关键字。
  3. 非根节点中至少有Math.ceil(m/2)-1个关键字。
  4. 每个节点中的关键字都按照从小到大的顺序排列,每个关键字的左子树中的值都小于它,每个右子树的值都大于它。
  5. 所有叶子节点都位于同一层。

在这里插入图片描述

如图是一个4阶B树,每个节点最多个m-1= 3个关键字,非叶子节点至少有Math.ceil(m/2)-1=1个关键字。

B树的插入操作

如果B树中已经存在需要插入的值,则替换掉。如果没有直接添加。

添加步骤如下:

  1. 根据插入的值找到叶子节点并插入。
  2. 判断当前节点的个数是否小于等于m-1,满足结束,否则进行下一步
  3. 以节点中间值(如果是偶数个时选择前一个或者后一个都可以)为中心分裂成左右两个部分,然后将中间值插入到父节点中,插入到父节点后这个中间值左子树指向左半部分,右子树指向右半部分,然后当前节点指向父节点,继续进行第三步。

下面以4阶数为例

先在根节点中插入20、39、91

在这里插入图片描述

在插入40

在这里插入图片描述

节点的关键字个数为4大于m-1,按照第三步:我们选择前一个提取。
在这里插入图片描述

插入53,21

在这里插入图片描述

插入40

在这里插入图片描述

插入节点关键字个数大于m-1,需要分裂:

在这里插入图片描述

插入30,27

在这里插入图片描述

插入33

在这里插入图片描述

插入35

在这里插入图片描述

添加35后分裂得到上图,30插入到父节点后,父节点被称为当前节点,当前节点关键字多了。分裂得到:

在这里插入图片描述

删除操作

如果B树中不存在要删除的值则失败。

  1. 当前需要删除的值在非叶子节点上,则用后续的值替换当前位置。然后在后继节点中删除后继值。此时如果后继节点的关键字个数如果大于等于Math.ceil(m/2)-1,删除结束,否则执行下一步。
  2. 如果兄弟结点key个数大于Math.ceil(m/2)-1,则父结点中的key下移到该结点,兄弟结点中的一个key上移,删除操作结束。否则,将父结点中的key下移与当前结点及它的兄弟结点中的key合并,形成一个新的结点。原父结点中的key的两个孩子指针就变成了一个孩子指针,指向这个新结点。然后当前结点的指针指向父结点,重复上第2步。

下面以5阶B树为例删除:

原数据如下
在这里插入图片描述

删除21:删除21后判断当前节点的关键字个数大于等于Math.ceil(m/2)-1,删除结束。

在这里插入图片描述

删除27:27为非叶子节点上的值,所以利用后继记录28替换他。
在这里插入图片描述

从图中看出,28替换后原28所在节点的关键字个数小于Math.ceil(m/2)-1。删但是它的兄弟节点有富裕的关键字(也就是兄弟节点关键字个数大于Math.ceil(m/2)-1)。向兄弟节点借一个。所以28下移,26上移。

在这里插入图片描述

删除24:在叶子节点直接删除24

在这里插入图片描述

发现当前节点关键字个数小于Math.ceil(m/2)-1,此时兄弟节点也只有两个关键字,不能借,只能父节点下沉与两个子节点组成新的节点。

在这里插入图片描述

删除40:直接删除后:

在这里插入图片描述

同删除24一样,父节点值下沉:

在这里插入图片描述

发现父节点的关键字又小于Math.ceil(m/2)-1,父节点的兄弟节点也不能借,父节点的父节点下沉。

在这里插入图片描述

B+树

B+树的定义

在这里插入图片描述

B树和B+树十分类似,B+树的所有叶子节点是链通的(下文中为了画图方便没有体现链接),B+树的关键字个数=最大孩子个数-1;B+树就是将所有数据存储在叶子节点上,非叶子节点只用于索引。上图为4阶B+树,黑色为索引。彩色为叶子节点存储真正的数据。

B+树的插入操作

  1. 若为空树,创建节点,直接插入值,此时节点也为根节点。
  2. 针对叶子类型节点:根据值找到待插入的叶子节点位置。插入后判断节点的值的个数是否小于m-1,是则插入结束,不是则将这个叶子节点分裂成两个叶子节点,左叶子节点包含前m/2个记录,右节点包含剩下的记录,将第m/2+1个记录值放进父节点,然后执行下一步。
  3. 针对索引节点:如果当当前节点记录个数小于等于m-1,插入结束。否则,将这个索引类型节点分裂成两个,左索引节点包含(m-1)/2个记录,右节点树包含m-(m-1)/2个记录,第m/2个节点插入到父节点中。重复第三步。

以5阶B+树为例:

首先依次插入:8,15,5,10
在这里插入图片描述

插入16:在当前节点插入16后:

在这里插入图片描述

发现节点的记录值大于m-1,需要将前(m-1)/2作为左子树,第m/2个记录作为父节点的值,m/2及其后面的记录作为右子树。

在这里插入图片描述

插入17:

在这里插入图片描述

插入18

在这里插入图片描述

调整元素位置:

在这里插入图片描述

添加数据直到下图:

在这里插入图片描述

现在添加7:节点记录大于m-1
在这里插入图片描述

进行分裂:

在这里插入图片描述

此时父节点记录个数大于m-1,执行第三步:需要将前(m-1)/2作为左子树,第m/2个记录作为父节点的值,m/2以后的记录作为右子树。

在这里插入图片描述

非叶子节点也称为内部节点,表示索引,并且它左子树都小于它,它的右子树都大于它。

删除操作

  1. 删除叶子结点中对应的值。删除后若结点的值的个数大于等于Math.ceil(m-1)/2 – 1,删除操作结束,否则执行第2步。
  2. 若兄弟结点值有富余(大于Math.ceil(m-1)/2 – 1),向兄弟结点借一个记录,同时用借到的值替换父结(指当前结点和兄弟结点共同的父结点)点中的值,删除结束。否则执行第3步。
  3. 若兄弟结点中没有富余的记录,则当前结点和兄弟结点合并成一个新的叶子结点,并删除父结点中的记录(父结点中的这个记录两边的孩子指针就变成了一个指针,正好指向这个新的叶子结点),将当前结点指向父结点(必为索引结点),执行第4步(第4步以后的操作和B树就完全一样了,主要是为了更新索引结点)。
  4. 若索引结点的记录的个数大于等于Math.ceil(m-1)/2 – 1,则删除操作结束。否则执行第5步
  5. 若兄弟结点有富余,父结点记录下移,兄弟结点记录上移,删除结束。否则执行第6步
  6. 当前结点和兄弟结点及父结点下移记录合并成一个新的结点。将当前结点指向父结点,重复第4步。

注意,通过B+树的删除操作后,索引结点中存在的key,不一定在叶子结点中存在对应的记录。也就是在删除时如果叶子结点中没有相应的key,则删除失败。

初始值:

在这里插入图片描述

删除22:根据步骤一,删除后节点值个数大于等于Math.ceil(m-1)/2 – 1,删除结束。

在这里插入图片描述

删除15:删除后的节点值个数小于Math.ceil(m-1)/2 – 1,执行第二步。

在这里插入图片描述

兄弟结点值有富余(大于Math.ceil(m-1)/2 – 1),向兄弟结点借一个记录,同时用借到的值替换父结(指当前结点和兄弟结点共同的父结点)点中的值。可以从兄弟结点借一个关键字为9的记录,同时更新将父结点中的关键字由10也变为9,删除结束。

在这里插入图片描述

删除7:删除7之后当前节点只有一个记录,小于Math.ceil(m-1)/2 – 1。而兄弟节点也都不能提供借出,只能将它与一个兄弟节点合并。

在这里插入图片描述

执行第四步:合并完成后,父节点记录个数小于Math.ceil(m-1)/2 – 1。兄弟节点也没有多余的记录可以借,那就合并。

在这里插入图片描述

执行第六步:

在这里插入图片描述

B树和B+树的区别?

B树和B+树主要有两个区别:

  • B树的叶子节点和非叶子节点都可以存放键和值,B+树所有数据存储在叶子节点,非叶子节点只存放键。
  • B+树的叶子节点是联通的,方便顺序检索。

MySQL数据库为啥用B+树作为索引,而不用B树?

  • B+树可以随机查询也可以顺序查询,而B树只能随机查询。
  • B+树更加节省空间。B树每个节点都存储键和值,而B+树的内部节点只存储键,这样一个节点就可以存储更多的索引,使得树的高度变低,提高了IO的效率。
  • B+树的叶子节点是链接的,可以方便范围查找和顺序查找。
  • B+树的性能更加稳定,每次查询都是从根节点到叶子,而B树可能在内部某个节点就已经找到查找到了。

什么时候使用B树合适呢?因为B树在内部节点也会存储值,所以将一些热点访问数据放在距离根节点进的地方,可以提高数据访问效率。综上所说B+树更适合作为索引的结构。

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

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

相关文章

深入理解python虚拟机:程序执行的载体——栈帧

栈帧(Stack Frame)是 Python 虚拟机中程序执行的载体之一,也是 Python 中的一种执行上下文。每当 Python 执行一个函数或方法时,都会创建一个栈帧来表示当前的函数调用,并将其压入一个称为调用栈(Call Stac…

RT1052的EPWM

文章目录 1 EPWM介绍1.1 引脚1.2 时钟1.3 比较寄存器 2 函数 1 EPWM介绍 RT1052 具有 4 个 eFlexPWM(eFlexWM1~eFlex_PWM4)。 每个 eFlexPWM 可以产生四路互补 PWM即产生 8 个 PWM,也可以产生相互独立的 PWM 波。四路分别是模块0-3每个 eFlexPWM 具有各自的故障检…

如何学习专业的学术用语01

问题的提出——凭啥人家写的词汇这么专业 做法一 做法二:做一个专业数据库 专门做教育技术类的

换过3个工作,我却得出10年测试人的血泪经验

我跟大多数IT职场的测试新人起点差不多,在测试的这条路上,没有天生的聪明天资,也没有一个耀眼的学历。在北京这样一个随便一个同事不是清华的本硕,就是北邮北航的硕士下,自己也常常感到惭愧。 自己从事测试多年&#…

论文笔记 Graph Attention Networks

2018 ICLR 1 intro 1.1. GCN的不足 无法完成inductive任务 inductive任务是指: 训练阶段与测试阶段需要处理的graph不同。通常是训练阶段只是在子图上进行,测试阶段需要处理未知的顶点。GGN 的参数依赖于邻接矩阵A/拉普拉斯矩阵L,所以换了…

一个完整挖洞 /src 漏洞实战流程【渗透测试】

目录: 1.如何找漏洞 2.找到后如何挖漏洞 3.漏洞如何提交 只要搞渗透,不就会听到很多行业内人前辈一直在重复:“信息搜集” 信息搜集有多重要,你搜集的到的多少资产信息,决定了你后续进行的一系列实战到什么程度! 要说 SQL 注入的漏洞咋找…

【博客700】如何使用 Nginx Ingress 快速实现金丝雀与蓝绿部署

如何使用 Nginx Ingress 快速实现金丝雀与蓝绿部署 背景 越来越多的应用采用微服务架构,应用数量相比传统模式更多,管理更加复杂,发布更加频繁,如果直接将新版本上线发布给全部用户。一旦遇到线上事故(或BUG&#xff…

Selenium的使用:WEB功能测试

Selenium是ThrougthWorks公司一个强大的开源WEB功能测试工具系列,本系统包括多款软件 Selenium语言简单,用(Command,target,value)三种元素组成一个行为,并且有协助录制脚本工具,但Selenese有一些严格的限制: …

在字节和滴滴划水四年,过于真实了...

先简单交代一下,我是某不知名211的计算机本硕,18年毕业加入滴滴,之后跳槽到了头条,一直从事测试开发相关的工作。之前没有实习经历,算是四年半的工作经验吧。 这四年半之间完成了一次晋升,换了一家公司&am…

torch.cuda.is_available()为false的解决办法

一、问题 在进行torch进行开发的过程中,我们习惯性的会使用pip install torch这样的方式来安装torch的包。 其实这样的是安装CPU的torch。 在导入包,执行下面代码的过程中,会出现结果为false。 import torchprint(torch.cuda.is_availabl…

04-数据集汇总

一、3D检测数据集 1、Argoverse数据集[参考] 年份:2019年; 作者:Argo AI等; 场景数:共113个场景,室外,包括USA,Pennsylvania,Miami,Florida等&#xff1b…

Django进阶:DRF(Django REST framework)

什么是DRF? DRF即Django REST framework的缩写,官网上说:Django REST framework是一个强大而灵活的工具包,用于构建Web API。 简单来说:通过DRF创建API后,就可以通过HTTP请求来获取、创建、更新或删除数据(…

CFDEM-OpenFOAM-Yade安装教程

在网上搜索与OpenFOAM相关的颗粒两相流计算资料时,发现了一个CFD-DEM coupled simulations with Yade and OpenFOAM。 在此之前,我学习过OpenFOAM自带的颗粒计算求解器,但是自带的求解器有很多缺点,最大的缺点就是颗粒运动方程的求…

10. 实现业务功能--退出登录

目录 1. 实现 Controller 2. 单体测试 3. 实现前端界面 退出的具体实现逻辑如下: 1. 用户访问退出接口 2. 服务器注销 Session( 在 Controller 中可以直接进行处理 ) 3. 返回成功或失败 4. 如果返回成功浏览器跳转到相应页面 5. 结束 一般来说&#…

Python入门--开发工具

Python是一种优秀的编程语言,具有简单易学、开放源代码、高效可靠等特点,广泛应用于Web开发、科学计算、数据分析、人工智能等领域。以下是常用的Python开发工具: PyCharm:JetBrains公司开发的Python IDE,功能强大&…

VMware vSphere Client端设置热添加虚拟机的CPU和内存

使用vSphere Client连接到VMware ESXi Server,在“配置→网络”中,可以看到,当前有两个虚拟交换机,并且为该虚拟交换机分配了管理地址10.10.228.81,点击“添加网络”如图所示。 添加配置向导,在网络类型&am…

AIGC的变革

AIGC(Artificial Intelligence and General Computing)是一个涵盖人工智能和通用计算的领域,它的发展前景非常广阔。以下是一些关于AIGC发展前景的观点: 人工智能市场增长迅速:随着人工智能技术的迅猛发展,…

嵌入式学习之投票系统改进版本

今天周六,9点钟就开始写代码,但是呢,一直在家里面,真的很容易心烦气躁,我正在研究有没有什么方法可以改变我的状态,今天写的代码是做昨天做的选票系统的改进,代码如下:

C语言实现贷款计算器

等额本金,等额本息数学推导:贷款 买房,利息怎么算?不要被忽悠了!李永乐老师讲等额本金和等额本息 一个心血来潮的研究,避免以后买房被坑。 捣鼓了半天才发现原来支付宝的那个利率是年利率不是月利率,坑了…

猿人学刷题系列(第一届比赛)——第四题

题目:采集这5页的全部数字,计算加和并提交结果 地址:https://match.yuanrenxue.cn/match/4 页面分析 首先打开开发者工具然后刷新界面进行抓包。 通过返回的数据来看,我们需要的数据极有可能是位于info键对应的值中,…