B树和B+树(平衡多路查找树)

news2024/12/22 19:57:13

文章目录

    • 为什么需要B树
    • B 树的特点
    • B树的查找
    • B+树的引入
    • B树的删除

链接:https://www.cs.usfca.edu/~galles/visualization/Algorithms.html

在这里插入图片描述

可以点击 Indexing 下的 B Trees 和 B+ Trees 去学习。

为什么需要B树

对 B 树的需求随着访问物理存储介质(如硬盘)的时间减少而增加。辅助存储设备速度较慢,容量较大。需要这种类型的数据结构来最大限度地减少磁盘访问。

其他数据结构如二叉搜索树、avl 树、红黑树等只能在一个节点中存储一个键。如果必须存储大量键,则此类树的高度将变得非常大,并且访问时间也会增加。

但是,B 树可以在单个节点中存储许多键,并且可以有多个子节点。这大大降低了高度,允许更快的磁盘访问。

B- 树和 B 树都指的都是 B 树,此外还有 B+ 树。

B 树的特点

可以把 B 树理解为一个有序的多叉树。

满足下列要求的 m 阶树:

(1)每个节点最多拥有 m 个孩子结点(即至多有 m-1 个关键字)

(2)每个结点的结构为

在这里插入图片描述

第一个位置的 n 用来表示结点有多少个关键字。
Pn 表示子树的指针,顺着指针可以找到子树的位置。
k 表示关键字。

例如:m = 4 的 4 阶 B 树

在这里插入图片描述

(3)除根节点外,其他结点至少有 m / 2 (向上取整)个孩子结点。

(4)若根节点不是叶子结点,则根节点至少有两个孩子结点。

(5)所有叶子结点都在同一层上,即B树是所有结点的平衡因子均等于0的多路查找树。

(6)除根节点外,其他节点都包含 n 个 key ,其中 [m/2]-1<=n<=m-1。

B树的查找

已知一棵三阶 B 树如下图所示,给出在 B 树中查找 37 的过程。

在这里插入图片描述
查找37,根节点是48,48>37,看48的左子树,25<37,看25的右子树,37=37。

那具体是怎么查找的呢??

首先来了解一下操作系统的磁盘预读。

磁盘预读:

  • 内存跟磁盘发生数据交互的时候,一般情况下有一个最小的逻辑单元,称之为页,datapage。
  • 页一般由操作系统决定是多大,一般是4k或者16k,我们在数据交互时,可以取页的整数倍来进行读取。

CPU要先把数据加载到内存中然后磁盘从内存中读取数据。

在这里插入图片描述

比如说这个 word 文档右击查看它的属性,虽然大小是46.9KB,但是占用空间是48KB,这是4K的整数倍,也就是磁盘加载数据到内存中都是datapage的整数倍。

在这里插入图片描述

我们可以结合操作系统知识理解 B 树的查找过程。

键值:表中的主键
指针:存储子节点的信息
数据:表记录中除主键外的数据

在这里插入图片描述

B树的每一个结点都是放在磁盘块里的,且一般规定磁盘块大小是16K

假如要在图中找一个关键字为28的数据:

首先把磁盘上的这个块加载到内存里,16<28,34>28,找到磁盘块1的p2,这是进行的第一次IO。

在这里插入图片描述

然后顺着磁盘块1的p2找到磁盘块3,再把磁盘块3加载到内存里面,然后28<25,28>31,找到磁盘块3的p2了。这是第二次IO。

在这里插入图片描述

然后顺着磁盘块3的p2找到磁盘块8,再把磁盘块8加载到内存里,28=28,返回关键字28对应的data。这是第三次IO。

在这里插入图片描述

B+树的引入

现在这个B树总共有三层,每个结点 datapage 是 16k ,假设指针和关键字不占用 datapage (占用很小),每个 data 占用 1k ,所以三层 B 树可以存储的 data 个数是16*16*16=2^12=4096条,还是在不考虑指针和关键字的 datapage 情况下的。所以如果要是存 10000 条数据的时候怎么办呢?或许你想到的是再给 B 树加一层,确实可以这样存储 10000 条数据,但是这样的话层数增多了,查找数据就要再多一次 IO 操作,再多一次 IO 操作那查找的速度不就又慢了吗?

在这里插入图片描述
那为什么 B 树要存储更多数据只能增加层数呢?因为存储空间都用来放 data 了,如果只存指针和关键字的话所占用的磁盘空间是非常小的,所以我们可以把 data 都放在叶子结点上,非叶子结点只存指针和关键字,可以提升查找速度,这就是 B+ 树

在这里插入图片描述

B+ 树结构长这样:

在这里插入图片描述

datapage 还是 16k ,假设每对指针和关键字(例如 上图磁盘块1的p1 ,28 )只占 10 个字节,那么一个结点可以存16000/10=1600个数据,三层结构可以存储 1600*1600*1600 千万级数据,存储的数据是非常多的。

B树的删除

已知一棵 5 阶(度)B 树如下图所示,给出在B树中删除 80、200、180、50、140 的过程。

在这里插入图片描述

要将删除非叶子节点的关键字转换为删除叶子节点关键字。在 B 树性质里,m阶树,除根节点外,其他节点都包含 n 个 key ,其中 [m/2]-1<=n<=m-1

如果节点删除一个关键字后,节点关键字依然大于 [m/2]-1个,那么不需要去做任何的变动直接删除就可以;如果删除关键字后小于 [m/2]-1个key,那么就需要让下一个节点的关键字补上来

在 B 树中删除 80、200、180、50、140 的过程如下:

  • 删除 80 :删除 80 后,节点关键字依然大于等于 2 个,那么不需要去做任何的变动直接删除就可以。
  • 删除 200 :删除 200 后节点关键字是 1 个,所以如果要删除 200 ,那么就要先找到 200 的下一个关键字,230,让 230 代替 200 ,然后再删掉 230 。
    在这里插入图片描述
  • 删除180:如果删除的是 180(此时已经删除 200 ),此节点只有一个关键字不满足节点关键字 >= 2 。
    在这里插入图片描述
    那么需要让父节点 230 代替 180 ,再让子节点 240 补上原来 230 的位置,才能仍满足每个节点关键字 >= 2 ,结果如下:
    在这里插入图片描述
  • 删除 50 :删除 50 后该节点关键字个数为 1 ,需要再加 1 个关键字才能满足B树性质,但是它的兄弟节点都是 2 个关键字,没法再给它一个关键字了,所以这个时候就需要找父节点要一个关键字(兄弟没有钱时找爸爸要)。
    在这里插入图片描述
    那么此时就先把父节点拉下来一个关键字。
    在这里插入图片描述
    然后再把兄弟节点合并了。
    在这里插入图片描述
    此时父节点不够两个关键字,那么需要找父节点的兄弟节点要一个关键字,如果父节点的兄弟节点没有关键字,那么就找父节点的父节点的父节点要一个关键字(爸爸找兄弟借,兄弟也没有那就找爷爷借),所以只能降低树的高度,变成了下面这样。
    在这里插入图片描述
    然后发现没有根节点,所以把兄弟节点进行合并,变成一个正常的 B 树。
    在这里插入图片描述
  • 删除 140 :删除 140 后,变成了这样。
    在这里插入图片描述
    然后从父节点拿一个关键字,变成了这样。
    在这里插入图片描述
    为了维持 B 树的特点再和兄弟节点进行合并,最终结果就是这样。
    在这里插入图片描述

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

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

相关文章

【Java】反射, 枚举,Lambda表达式

✨博客主页: 心荣~ ✨系列专栏:【Java SE】 ✨一句短话: 难在坚持,贵在坚持,成在坚持! 文章目录一. 反射1. 反射的概述2. 反射的使用2.1 反射常用的类2.2 通过反射获取Class对象2.3 获得Class类相关的方法2.4 使用反射创建实例对象2.5 使用反射获取实例对象中的构造方法2.6 通过…

Spring学习第1篇:学习spring必备的概念知识

大家家好&#xff0c;我是一名网络怪咖&#xff0c;北漂五年。相信大家和我一样&#xff0c;都有一个大厂梦&#xff0c;作为一名资深Java选手&#xff0c;深知Spring重要性&#xff0c;现在普遍都使用SpringBoot来开发&#xff0c;面试的时候SpringBoot原理也是经常会问到&…

纸牌博弈问题

纸牌博弈问题 作者&#xff1a;Grey 原文地址&#xff1a; 博客园&#xff1a;纸牌博弈问题 CSDN&#xff1a;纸牌博弈问题 题目描述 有一个整型数组 A&#xff0c;代表数值不同的纸牌排成一条线。玩家 a 和玩家 b 依次拿走每张纸牌&#xff0c; 规定玩家 a 先拿&#xff…

win11开机音效设置的方法

微软为win11重做了开机音效&#xff0c;与我们一直以来使用的开机音效不太一样&#xff0c;听起来很不舒服&#xff0c;因此我们可以通过设置开机音效的方法来修改它&#xff0c;只要在个性化设置中就可以找到了&#xff0c;下面一起来试试看吧。 win11开机音效怎么设置&#…

wordpress图片压缩插件-免费批量wordpress图片压缩

wordpress图片压缩插件&#xff0c;相信每个人都知道图片的太大会影响到网站的加载速度。过多的图像会对服务器产生相应的压力。导致网站打开会越来越慢。而图片也是会被搜索引擎收录的&#xff0c;可以在百度图片里面能搜索的到&#xff0c;也算是增加了网站的宣传力度。今天给…

(附源码)计算机毕业设计SSM基于微信平台的匿名电子投票系统

&#xff08;附源码&#xff09;计算机毕业设计SSM基于微信平台的匿名电子投票系统 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。…

【微信小程序支付功能】uniapp实现微信小程序支付功能

支付实现流程 首先前端写一个页面&#xff0c;简单说就是有一个输入支付金额的 然后有一个按钮&#xff0c;点击可以支付。 点击按钮后触发支付方法&#xff0c;就是我下面写的这些代码&#xff0c;复制就可以了。 然后先请求后端的一个方法&#xff0c;把你的价格还有openid之…

在Vue中使用Swiper轮播图、同时解决点击轮播图左右切换按钮不生效的问题、同时将轮播图抽离出为一个公共组件

轮播图左右的切换按钮、如果点击没有反应&#xff0c;控制台也没有报错。很大可能是版本问题。如果不指定版本信息、默认安装的是最新的版本。版本过高或者过低都有可能导致无效。目前兼容性和稳定性比较好的是&#xff1a;5.4.5。 官网地址&#xff1a;https://www.swiper.com…

【隧道应用-1】netsh端口映射内网

1、端口映射 是指将一台主机的内网&#xff08;LAN&#xff09;IP 地址映射成一个公网&#xff08;WAN&#xff09;IP 地址&#xff0c;当用户访问提供映射端口主机的某个端口时&#xff0c;服务器将请求转移到本地局域内部提供这种特定服务的主机&#xff1b;利用端口映射功能…

猿创征文|程序员的浪漫(代码猜诗词)

✅作者简介&#xff1a; 全栈领域新星创作者&#xff0c;阿里云专家博主&#xff0c;华为云云享专家博主&#xff0c;掘金后端评审团成员&#xff0c; &#x1f495;前言&#xff1a;在大众的认知里&#xff0c;程序员只是一群坐在电脑前熬夜敲代码的…

webrtc 笔记

webrtc主要步骤 navigator.mediaDevices.getUserMedia({audio:true,redio:true}) 获取用户的摄像头状态,返回媒体流,把媒体流赋给video的srcObject属性,就能在页面上展示自己的音视频 let peer new RTCPeerConnection(servers) 创建peer实例,通过这个实例的一系列方法实现p2p…

vue3 :一个实用的 vite + vue3 组件库脚手架工具

目录 1 组件库脚手架内容 2 组件库脚手架技术栈 3 使用说明 3.1 克隆代码到本地 3.2 安装依赖 3.3 本地开发 3.4 创建新组件 3.5 构建文档 3.6 构建 example 3.7 发布组件库 4 组件库命令说明 无论是 vue2 全家桶还是 vue3 vite TypeScript&#xff0c;组件库的使…

无需购买服务器,用cpolar发布本地web网站

随着互联网的快速发展&#xff0c;网络也成为我们生活中不可缺少的必要条件&#xff0c;为了能在互联网世界中有自己的一片天地&#xff0c;建立一个属于自己的网页就成为很多人的选择。但互联网行业作为资本密集的行业&#xff0c;委托别人建立一个像样的网站要花费不少&#…

一文搞定基因型数据清洗

文章目录数据1 二进制文件2. plink二进制文件变为文本文件&#xff08;ped和map&#xff09;3. plink将vcf转化为plink文件4. 提取样本和SNP4.1 提取样本4.2 提取SNP5. plink和表型数据合并6. 数据汇总6.1 次等位基因频率&#xff08;maf&#xff09;6.2 缺失6.3 哈温检测6.4 杂…

JDBC-01:如何获取数据库连接

文章目录初步了解jdbcJDBC程序编写步骤Driver接口介绍导入驱动&#xff08;idea&#xff09;加载与注册JDBC驱动要素一&#xff1a;URL要素二&#xff1a;用户名和密码获取数据库连接获取数据库连接的方式一获取数据库连接的方式二获取数据库连接的方式三获取数据库连接的方式四…

FreeRTOS移植STM32 printf()函数重定向到USART3

我们在移植FreeRTOS过程中如果没有printf()函数打印调试信息到串口精灵&#xff0c;则程序开发就会非常不方便。本文实现STM32工程上的printf()函数&#xff0c;方便用于程序开发中调试信息打印到电脑上的串口调试精灵。 最简单的方法就是使用MicroLIB库。 一、KEIL-MDK中勾选U…

字体管理工具 - RightFont使用教程

RightFont RightFont是 Mac OS X 上一款非常轻巧的字体管理工具&#xff0c;目前已经完成了与 PhotoShop、Sketch 两大设计应用的集成。RightFont 是 Mac系统上一款优秀的字体管理工具&#xff0c;专为设计师设计&#xff0c;轻量化和简洁&#xff0c;可以方便快速的管理你的字…

《C陷阱与缺陷》读书笔记1

词法分析&#xff1a;贪心法 主要就是解释词法分析时的原则&#xff0c;即&#xff1a; 编译器将程序分解为符号时&#xff0c;从左到右一个字符接一个字符的读入。如果编译器的输入流截止至某个字符之前都已经被分解为一个个符号&#xff0c;那么下一个符号将包括从该字符之…

Linux文件锁的使用

文件是一种共享资源,多个进程对同一文件进行操作的时候,必然涉及到竞争状态&#xff0c;因此引入了文件锁实现对共享资源的访问进行保护的机制&#xff0c;通过对文件上锁&#xff0c; 来避免访问共享资源产生竞争 状态。 一、文件锁的分类 1.建议性锁 建议性锁本质上是一种协…

Java并发编程——Threadlocal源码解析

Threadlocal源码解析一、基本结构二、ThreadLocal操作set操作get操作remove操作三、内存泄露&#xff1f;四、ThreadLocalMap核心变量数组下标计算方式阈值计算扩容下标冲突&#xff08;hash冲突&#xff09;从名称上来看可以理解为线程本地变量&#xff0c;也可以认为是线程局…