数据结构 B树 B+树 B*树 特性与规则说明 图解

文章目录

  • 前言
  • B树基本规则
  • B树的数据插入(文字描述+图解)
  • B树数据查找
  • B树效率分析
  • B树的作用
  • B+树基本规则
  • B+树 与 B树对比
  • B*树基本规则
  • B*树 与 B+树对比
  • 拓展

前言

B树基本规则

  1. 每个节点最多有m个子节点,其中m是一个正整数。根节点除外,其他节点至少有⌈m/2⌉个子节点。

  2. 每个节点中的键值按照非降序排列。对于节点中的键值k,如果有n个子节点,那么节点中的n-1个键值将把节点分为n个区间,第i个区间的键值小于k,第i+1个区间的键值大于等于k。

  3. 所有叶子节点位于同一层,且不包含任何键值信息,可以看作是外部存储的块。

  4. 每个非叶子节点中的键值个数比子节点个数少1。

  5. 每个节点中的键值个数满足:
    ⌈m/2⌉-1 <= 键值个数 <= m-1

![在这里插入图片描述](https://img-blog.csdnimg.cn/7608c2a7fa9a45efbafd86029ce6b7a1.png

B树的数据插入(文字描述+图解)

插入规则概览:

1.从根节点开始,按照节点中的键值进行比较,找到合适的叶子节点(比较结果类似于二叉搜索树)。

2.如果叶子节点中已经存在该键值,则更新相应的值。

3.如果叶子节点中不存在该键值,则将键值插入到叶子节点的合适位置,并保持节点中的键值有序。

4.如果插入键值后,叶子节点的键值个数超过了上限m-1,则进行分裂操作。

将叶子节点的键值分成两部分,左边部分包含⌈(m-1)/2⌉个键值,右边部分包含⌊(m-1)/2⌋个键值。将右边部分的键值和对应的子节点分离出来,形成一个新的叶子节点。将新的叶子节点插入到叶子节点的右边,并更新父节点的键值信息。

5.如果插入键值后,叶子节点的键值个数没有超过上限m-1,则直接插入。

6.如果父节点存在并且插入键值后超过了上限m-1,则进行分裂操作。

将父节点的键值分成两部分,左边部分包含⌈(m-1)/2⌉个键值,右边部分包含⌊(m-1)/2⌋个键值。将右边部分的键值和对应的子节点分离出来,形成一个新的父节点。将新的父节点插入到父节点的右边,并更新祖父节点的键值信息。

重复步骤6,直到根节点为止。

(图解)插入的情况归类为以下几种:

  1. 无父亲节点,不需要分裂;
    在这里插入图片描述

  2. 有父亲节点,不需要分裂;
    在这里插入图片描述

  3. 无父亲节点,需要分裂;
    在这里插入图片描述

    将叶子节点的键值分成两部分,左边部分包含⌈(m-1)/2⌉个键值,右边部分包含⌊(m-	1)/2⌋个键值。将右边部分的键值和对应的子节点分离出来,形成一个新的叶子节点。
    
  4. 有父亲节点,插入节点需要分裂,插入后父亲节点不需要分裂;
    在这里插入图片描述
    将叶子节点的键值分成两部分,左边部分包含⌈(m-1)/2⌉个键值,右边部分包含⌊(m-1)/2⌋个键值。
    将右边部分的键值和对应的子节点分离出来,形成一个新的叶子节点。

    将新的叶子节点插入到叶子节点的右边,并更新父节点的键值信息。

  5. 有父亲节点,插入节点需要分裂,插入后父亲节点需要分裂;

在这里插入图片描述

将父节点的键值分成两部分,左边部分包含⌈(m-1)/2⌉个键值,右边部分包含⌊(m-1)/2⌋个键值。将右边部分的键值和对应的子节点分离出来,形成一个新的父节点。将新的父节点插入到父节点的右边,并更新祖父节点的键值信息。重复以上步骤,直到根节点

B树数据查找

由于数据数据排列的格式类似于搜索二叉树,所以查找也是。

B树效率分析

如果忽略内存中查找和外存中查找时间的巨大差异:
设 :
有效值个数 = N;
度 = M ;
则:一个节点的有效值个数 = M/2 ~ M-1 ;
故:树的高度为 = log{M/2} N ~ log{M-1}N ;
一个节点内查找的复杂度 = O(log{2}M/2 ) ~ O(log{2}M-1 ) ;
故:最终时间复杂度 = [ O(log{2}M/2 ) ~ O(log{2}M-1 ) ] * [ log{M/2} N ~ log{M-1}N ]

但,实际应用情况不是这样,实际时间主要消耗在,从上级节点访问下级节点的过程中,因为访问节点其实是访问外存;

关键理解点)B树查找过程中,IO操作即为进入节点的操作,当查找过程中需要访问到磁盘上的节点时,就需要进行IO操作将节点从磁盘读取到内存中。

所以主要的时间消耗为:[ log{M/2} N ~ log{M-1}N ] 次访问外存的次数 !!!!

对于N = 62*1000000000个节点,如果度M为1024,则 l o g M / 2 N log_{M/2}N logM/2N <=
4,即在620亿个元素中,如果这棵树的度为1024,则需要小于4次即可定位到该节点,然后利用二分查找可以快速定位到该元素,大大减少了读取磁盘的次数。

B树的作用

数据库索引:B树常被用作数据库的索引结构,能够高效地支持数据的查找和范围查询。

文件系统:B树被用于文件系统中的目录结构,可以高效地支持文件的查找和管理。

缓存系统:B树可以用于缓存系统中的索引结构,加速数据的访问和查询。

路由表:B树可以用于路由表的存储和查找,快速定位目标地址。

B+树基本规则

  1. 分支节点的子树指针与关键字个数相同
  2. 分支节点的子树指针p[i]指向关键字值大小在[k[i],k[i+1])区间之间
  3. 所有叶子节点增加一个链接指针链接在一起
    所有关键字及其映射数据都在叶子节点出现(所有的数据都在最底一层存储)
  4. 所有关键字都出现在叶子节点的链表中,且链表中的节点都是有序的。
  5. 不可能在分支节点中命中数据(所有的数据都在最底一层存储)
  6. 分支节点相当于是叶子节点的索引,叶子节点才是存储数据的数据层。
    在这里插入图片描述

B+树 与 B树对比

先说结论:
1.B树更适合随机查找,B+树更适合范围查找
2.B+树相对更省空间
3.对数据进行插入、删除的时候B+树更高
原因:

  1. B树的每个节点包含关键字和对应的指针,用于存储数据和构建索引。B树的节点可以直接存储数据,因此在查找时可以直接定位到数据所在的节点。
    B+树的每个节点只包含关键字,数据存储在叶子节点中。叶子节点之间通过指针连接形成一个有序链表,叶子节点上的关键字也构成一个有序序列。B+树的非叶子节点仅用于索引,不存储数据,这样可以减少非叶子节点的数量,提高内存利用率。
  2. B树的节点既存储数据又存储索引,因此每个节点可以存储更多的数据。这样可以减少树的高度,提高查询效率。但是,由于B树的节点包含数据,插入和删除操作需要进行数据的移动和调整,相对较慢。
    B+树的非叶子节点仅用于索引,不存储数据,因此每个节点可以存储更多的索引。叶子节点之间通过指针连接形成有序链表,可以高效地进行顺序访问。同时,由于B+树的数据只存储在叶子节点中,插入和删除操作只需要调整索引节点,相对较快。

B*树基本规则

B*树是B+树的变形,在B+树的非根和非叶子节点再增加指向兄弟节点的指针。
在这里插入图片描述

B*树 与 B+树对比

结论: B*树空间利用率比B+树高

B+树的分裂:当一个结点满时,分配一个新的结点,并将原结点中1/2的数据复制到新结点,最后在父结点中增加新结点的指针;

B*树的分裂:当一个结点满时,如果它的下一个兄弟结点未满,那么将一部分数据移到兄弟结点中,再在原结
点插入关键字,最后修改父结点中兄弟结点的关键字(因为兄弟结点的关键字范围改变了);如果兄弟也满了,则在原结点与兄弟结点之间增加新结点,并各复制1/3的数据到新结点,最后在父结点增加新结点的指针。

拓展

B+树的插入操作规则如下:

查找插入位置:从根节点开始,按照B+树的搜索规则找到插入位置。如果插入的关键字已经存在于树中,则根据具体情况进行处理(如替换、忽略或合并等)。

插入到叶子节点:将新的关键字插入到叶子节点中的适当位置。如果插入后导致叶子节点的关键字数量超过了阶数的上限,则进行分裂操作。

叶子节点分裂:将超过阶数上限的叶子节点分裂成两个节点。将一半的关键字移动到新的节点中,并调整指针连接。同时,将新节点的最小关键字插入到父节点中。

父节点调整:如果叶子节点的分裂导致父节点关键字数量超过了阶数的上限,则进行递归的分裂操作。将超过阶数上限的父节点分裂成两个节点,并将新节点的最小关键字插入到父节点的父节点中。

递归调整:如果父节点的分裂导致祖先节点关键字数量超过了阶数的上限,则继续进行递归的分裂操作,直到根节点。

根节点分裂:如果根节点的分裂导致树的高度增加,则创建一个新的根节点,并将原来的根节点分裂成两个节点。将新的根节点的最小关键字插入到新的根节点中,并调整指针连接。

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

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

相关文章

聊聊并发编程——线程池

目录 Java线程池 处理流程 线程池主要参数 常见的拒绝策略 execute和submit区别 关闭线程池 常见的线程池 newSingleThreadExecutor newFixedThreadPool newCachedThreadPool newScheduledThreadPool 线程池的状态 Java线程池 运用场景最多的并发框架&#xff0c;…

阿里巴巴K8S集成seata

正文 在K8S集成seata&#xff0c;官方配置 代码 apiVersion: v1 kind: Service metadata:name: seata-servernamespace: wmz-devlabels:k8s-app: seata-server spec:type: NodePortports:- port: 8091nodePort: 30091protocol: TCPname: httpselector:k8s-app: seata-server-…

Java练习题-键盘录入字符串实现大小写转换

✅作者简介&#xff1a;CSDN内容合伙人、阿里云专家博主、51CTO专家博主、新星计划第三季python赛道Top1&#x1f3c6; &#x1f4c3;个人主页&#xff1a;hacker707的csdn博客 &#x1f525;系列专栏&#xff1a;Java练习题 &#x1f4ac;个人格言&#xff1a;不断的翻越一座又…

idea清空缓存类

解决办法 网上有很多是让你去清空什么maven依赖&#xff0c;但假如这个项目是你不可以大刀阔斧的话 可以清空idea缓存 选择 Invalidate 开头的 然后全选 运行重启idea OK

Linux系统编程系列之线程

一、什么是线程 线程&#xff08;Thread&#xff09;是计算机中的基本执行单元&#xff0c;是操作系统调度的最小单位。线程是进程内的一个独立执行流程&#xff0c;一个进程可以包含多个线程&#xff0c;这些线程共享进程的资源&#xff0c;但每个线程都有自己的独立栈空间以及…

Java后端模拟面试,题集①

1.Spring bean的生命周期 实例化 Instantiation属性赋值 Populate初始化 Initialization销毁 Destruction 2.Spring AOP的创建在bean的哪个时期进行的 &#xff08;图片转载自Spring Bean的完整生命周期&#xff08;带流程图&#xff0c;好记&#xff09;&#xff09; 3.MQ如…

基于SSM的选课排课系统

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用Vue技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

2023年中国奶牛平均单产量、奶类产量及发展趋势分析:液态奶市场向高端化发展[图]

2022年&#xff0c;我国奶产业素质稳步提升&#xff0c;全国存栏百头以上规模养殖比例达到72%&#xff0c;同比提高2个百分点。奶牛平均单产9.2吨&#xff0c;较2021年增加500千克&#xff1b;规模牧场95%以上配备全混合日粮搅拌车&#xff0c;原料奶生产100%实现机械化挤奶&am…

3D WEB轻量化引擎HOOPS助力3D测量应用蓬勃发展:效率、精度显著提升

在3D开发工具领域&#xff0c;Tech Soft 3D打造的HOOPS SDK已经崭露头角&#xff0c;成为了全球领先的3D领域开发工具提供商。HOOPS SDK包括四种不同的3D软件开发工具&#xff0c;已成为行业的翘楚。 其中&#xff0c;HOOPS Exchange以其CAD数据转换的能力脱颖而出&#xff0c…

如何破解压缩包zip解压密码?

Zip压缩包设置了密码&#xff0c;解压的时候就需要输入正确对密码才能顺利解压出文件&#xff0c;正常当我们解压文件或者删除密码的时候&#xff0c;虽然方法多&#xff0c;但是都需要输入正确的密码才能完成。忘记密码就无法进行操作。 那么&#xff0c;忘记了zip压缩包的密…

leetCode 55.跳跃游戏 贪心算法

给你一个非负整数数组 nums &#xff0c;你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。判断你是否能够到达最后一个下标&#xff0c;如果可以&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 示例 1&#xff1a; 输入…

基于微信小程序的手机在线商城小程序设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言系统主要功能&#xff1a;具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计…

MySql017——组合查询

一、UNION作用 可用UNION操作符来组合数条SQL查询。 二、UNION 使用规则 1、UNION的使用很简单。所需做的只是给出每条SELECT语句&#xff0c;在各条语句之间放上关键字UNION。2、UNION必须由两条或两条以上的SELECT语句组成&#xff0c;语句之间用关键字UNION分隔&#xff…

专业图像处理软件DxO PhotoLab 7 mac中文特点和功能

DxO PhotoLab 7 mac是一款专业的图像处理软件&#xff0c;它为摄影师和摄影爱好者提供了强大而全面的照片处理和编辑功能。 DxO PhotoLab 7 mac软件特点和功能 强大的RAW和JPEG格式处理能力&#xff1a;DxO PhotoLab 7可以处理来自各种相机的RAW格式图像&#xff0c;包括佳能、…

(SAR)Sentinel-1影像自动下载

基于ASF网站提供的python代码&#xff0c;实现Sentinel-1影像的自动下载&#xff1b; 1、登录ASF网站 登录Sentinel-1影像ASF网站&#xff1a;https://search.asf.alaska.edu/&#xff1b; 点击网站最右侧Sign in图标&#xff0c;进行用户注册&#xff1b; 注册完用户之后&…

【c语言】推箱子

所需知识&#xff1a;c语言枚举&#xff0c;数组&#xff0c;for循环&#xff0c;while循环&#xff0c;switch,case语句&#xff0c;图形库相关函数 1.调整控制台窗口大小 #define _CRT_SECURE_NO_WARNINGS #include <stdlib.h>#include <stdio.h> int main() {…

STM32之DMA

简介 • DMA &#xff08; Direct Memory Access &#xff09;直接存储器存取 &#xff08;可以直接访问STM32内部存储器&#xff0c;如SRAM、程序存储器Flash和寄存器等&#xff09; •DMA可以提供外设和存储器或者存储器和存储器之间的高速数据传输&#xff0c;无须CPU干预&a…

pytorch函数reshape()和view()的区别及张量连续性

目录 1.view() 2.reshape() 3.引用和副本&#xff1a; 4.区别 5.总结 在PyTorch中&#xff0c;tensor可以使用两种方法来改变其形状&#xff1a;view()和reshape()。这两种方法的作用是相当类似的&#xff0c;但是它们在实现上有一些细微的区别。 1.view() view()方法是…

古记事法:Windows 下 16 位汇编环境搭建指南(DOSBox-X 篇)

文章目录 参考环境DOSBox-XWOWWindows On Windows 产生的原因Windows On Windows 的工作原理WOW16 的结束与 WOW64 的未来 在现代操作系统中运行 16 位应用程序DOSBox-X 16 位汇编环境的搭建应用准备挂载自动挂载dosbox-x.conf配置工具 参考 项目描述搜索引擎Bing、GoogleAI 大…

二极管的直流等效电路和微变等效电路

二级管的主要参数 1.IF&#xff08;最大整流的电流&#xff09; 二极管长期工作做能够通过电流的平均最大值&#xff1a;物理意义&#xff1a;功率电流值。 2.UR 二极管最高反向工作电压 需要留有裕度&#xff0c;通常能达到一半的裕度&#xff1b;UR不能等于UBR。 3.IR 未击穿…