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

【B树、B-树、B+、B*树】

目录

  • 一、B-树(即B树)的定义及操作
    • 1.1、定义
    • 1.2、操作
      • 1.2.1、查找
      • 1.2.2、插入
      • 1.2.3、删除
  • 二、B+树的定义及操作
    • 2.1、定义
    • 2.2、操作
      • 2.2.1、查找
      • 2.2.2、插入
      • 2.2.3、删除
  • 三、B*树

一、B-树(即B树)的定义及操作

1.1、定义

B-tree即B树,B是Balanced,平衡的意思,因为B树的原英文名称为B-tree,国内很多人将其译为B-tree,所以B树就是B-树。

磁盘管理系统中的目录管理,以及数据库系统中的索引组织多数都采用B树这种数据结构。

一棵m阶的B树,或为空树,或是满足以下特性的m叉树:

  1. 树中每个结点至多有m棵子树;
  2. 若根结点不是叶子结点,则至少有两棵子树;
  3. 除根之外的所有非终端结点至少有[m/2](向上取整)棵子树;
  4. 所有叶子结点都出现在同一层次上,并且不带信息,通常称为失败结点(失败结点并不存在,指向这些结点的指针为空,引入失败结点是为了便于分析B树的查找性能);
  5. 所有非终端结点最少有[m/2]-1个关键字,最多有m-1个关键字,结点的结构如图所示:
    在这里插入图片描述
    其中,n为结点中关键字的个数,K为关键字,且在这里插入图片描述;P为指向子树根结点的指针,且指针在这里插入图片描述所指子树中所有结点的关键字均小于在这里插入图片描述在这里插入图片描述所指子树中所有结点的关键字均大于在这里插入图片描述
    对任一关键字K而言,在这里插入图片描述相当于指向其左子树,在这里插入图片描述相当于指向其右子树。
    B树具有平衡、有序、多路的特点。
    在这里插入图片描述
    具体实现时,为记录其双亲结点,B树结点的存储结构通常会增加一个parent指针,指向其双亲结点,如图:
    在这里插入图片描述
#define MaxSize 3typedef struct BTnode{int keynum;//结点中关键字的个数,即结点的大小struct BTnode *parent;//指向双亲结点ElemType key[m+1];//关键字向量,0号单元未用struct BTnode *ptr[m+1];//子树指针向量Record *recptr[m+1];//记录指针向量,0号单元未用
}BTnode, *BTree;//B树查找结果类型
typedef struct{BTnode *pt;int i;//1...m,在结点中的关键字序号int tag;//1:查找成功,0:查找失败
}Result;

1.2、操作

1.2.1、查找

算法思想:
将给定值key与根结点的各个关键字进行比较,由于该关键字序列是有序的,所以查找时可采用顺序查找,也可采用折半查找,查找时:

  1. 在这里插入图片描述,则查找成功;
  2. 在这里插入图片描述,则顺着指针在这里插入图片描述所指向的子树继续向下查找;
  3. 在这里插入图片描述,则顺着指针在这里插入图片描述所指向的子树继续向下查找;
  4. 在这里插入图片描述,则顺着指针在这里插入图片描述所指向的子树继续向下查找。
  5. 如果在自上而下的查找过程中,找到了关键字key,则查找成功,如果直到叶子结点也未找到,则查找失败。

1.2.2、插入

思想:针对m阶高度h的B树,插入一个元素时,首先在B树中是否存在,如果不存在,即在叶子结点处结束,然后在叶子结点中插入该新的元素。

  1. 若该结点元素个数小于m-1,则直接插入;
  2. 若该结点元素个数等于m-1,引起结点分裂,以该结点中间元素为分界,取中间元素(若中间元素为两个,则随机选取一个)插入到父结点中;
  3. 重复上述操作,直到所有结点符合B树的规则,最坏的情况是一直分裂到根结点,生成新的根结点,高度增加1。

示例分析:
以5阶B树为例,5阶B树的规则:

  1. 2<=根结点的子树<=5;
  2. 3<=分支结点的子树<=5
  3. 1<=根结点元素个数<=4
  4. 2<=分支结点元素个数<=4
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

1.2.3、删除

首先查找B树中需删除的元素,如果该元素在B树中存在,则将该元素在其结点中进行删除;删除该元素后,首先判断该元素是否有左右孩子结点,如果有,则上移孩子结点中的某相近元素(“左孩子最右边的节点”或“右孩子最左边的节点”)到父节点中,然后是移动之后的情况;如果没有,直接删除。

  1. 某结点中元素数目小于[m/2]-1,则需要看其某相邻兄弟结点是否丰满;
  2. 如果丰满(结点中元素个数大于(m/2)-1),则向父节点借一个元素来满足条件;
  3. 如果其相邻兄弟都不丰满,即其结点数目等于(m/2)-1,则该结点与其相邻的某一兄弟结点进行“合并”成一个结点;
    以5阶B树为例,详细讲解删除的动作:
    如图依次删除依次删除【8】,【20】,【18】,【5】
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

二、B+树的定义及操作

2.1、定义

B+树是应文件系统所需而产生的B树的变形树。
一棵m阶B+树满足以下条件:

  1. 每个结点最多有M个子结点;
  2. 非叶子结点的根结点至少有两个子结点;
  3. 除根结点外的分支结点至少有[m/2]个子结点;
  4. 有k棵子树的非叶子结点有k个关键字,且关键字按照升序排列;
  5. 叶结点在同一层次中。
  6. 所有叶子结点增加一个链接指针链接在一起;
  7. 所有关键字及其映射数据都在叶子结点中出现。
    在这里插入图片描述
    在这里插入图片描述
    优点:
    B+树的插入过程与B树基本类似,区别在于:
  8. 第一次插入两层结点,一层做分支,一层做根;
  9. B+树在分裂时,是将左半部分的数据保留,右半部分的数据放入新建兄弟结点中,并将新建结点中的最小值更新到父结点中。

2.2、操作

2.2.1、查找

若非终端结点上的关键字等于给定值, 并不终止,而是继续向下直到叶子结点。因此,在B+树中,不管查找成功与否,每次查找都是走了一条从根到叶子结点的路径。B+树查找的分析类似于B-树。

B+树不仅能够有效地查找单个关键字,而且更适合查找某个范围内的所有关键字。例如,在B+树上找出范围在[a, b]之间的所有关键字值。 处理方法如下:通过一次查找找出关键字 a, 不管它是否存在,都可以到达可能出现a的叶子结点,然后在叶子结点中查找关键字值等于a或大于a的那些关键字,对千所找到的每个关键字都有一个指针指向相应的记录,这些记录的关键字在所需要的范围。 如果在当前结点中没有发现大于b的关键字,就可以使用当前叶子结点的最后一个指针找到下一个叶子结点,并继续进行同样的处理,直至在某个叶子结点中找到大于b的关键字,才停止查找。

2.2.2、插入

仅在叶子结点上进行插入,当结点中的关键字个数大于m时要分裂成两个结点,它们所含关键字的个数分别为[(m+1)/2] 和 [(m+1)/2]并且,它们的双亲结点中应同时包含这两个结点中的最大关键字。

2.2.3、删除

B+树的删除也仅在叶子结点进行,当叶子结点中最大关键字被删除时,其 在非终端结点中的值可以作为一个 “分界关键字“ 存在。若因删除 而使结点中关键字的个数少于「m/2]时,其和兄弟结点的合 并过程亦和B-树类似。

三、B*树

B*树是在B+树的基础上,在B+树的非根和非叶子结点增加指向兄弟的指针,将结点的利用率从1/2提高到2/3。
在这里插入图片描述

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 框架设计MVC
  • 暴力风扇无刷电机驱动方案pcba设计研发
  • 阿里云短信PHP集成api类
  • 【gpt】学习笔记:ChatGPT 用于 3D 内容生成搭配nvidia deepsearch
  • stm32使用通用定时器生成pwm
  • jenkins系列-07.轻易级jpom安装
  • FPGA CFGBVS 管脚接法
  • 彻底改变时尚:使用 GAN 实现 AI 的未来
  • 【自撰写】【国际象棋入门】第11课 对局实例分析(一)
  • LabVIEW红外热波图像缺陷检
  • 不想填邀请码?Xinstall来帮你,一键安装无忧愁
  • Laravel数据库的魔法棒:深入探索数据库迁移(Migrations)
  • 云动态摘要 2024-07-16
  • 字符串类中的常用方法
  • datawhale - 基于术语词典干预的机器翻译挑战赛 (一)
  • [deviceone开发]-do_Webview的基本示例
  • Android Volley源码解析
  • android百种动画侧滑库、步骤视图、TextView效果、社交、搜房、K线图等源码
  • co.js - 让异步代码同步化
  • Git学习与使用心得(1)—— 初始化
  • hadoop入门学习教程--DKHadoop完整安装步骤
  • iOS 颜色设置看我就够了
  • iOS编译提示和导航提示
  • Java 网络编程(2):UDP 的使用
  • JAVA 学习IO流
  • js操作时间(持续更新)
  • js作用域和this的理解
  • JWT究竟是什么呢?
  • puppeteer stop redirect 的正确姿势及 net::ERR_FAILED 的解决
  • Redash本地开发环境搭建
  • vue从创建到完整的饿了么(11)组件的使用(svg图标及watch的简单使用)
  • 从零开始的无人驾驶 1
  • 大主子表关联的性能优化方法
  • 记一次删除Git记录中的大文件的过程
  • 聊聊spring cloud的LoadBalancerAutoConfiguration
  • 浅谈JavaScript的面向对象和它的封装、继承、多态
  • 吐槽Javascript系列二:数组中的splice和slice方法
  • 移动端唤起键盘时取消position:fixed定位
  • 走向全栈之MongoDB的使用
  • 你对linux中grep命令知道多少?
  • ​【已解决】npm install​卡主不动的情况
  • ​渐进式Web应用PWA的未来
  • # include “ “ 和 # include < >两者的区别
  • ### RabbitMQ五种工作模式:
  • #Datawhale AI夏令营第4期#AIGC方向 文生图 Task2
  • #gStore-weekly | gStore最新版本1.0之三角形计数函数的使用
  • #微信小程序:微信小程序常见的配置传旨
  • (力扣题库)跳跃游戏II(c++)
  • (企业 / 公司项目)前端使用pingyin-pro将汉字转成拼音
  • (完整代码)R语言中利用SVM-RFE机器学习算法筛选关键因子
  • (一)utf8mb4_general_ci 和 utf8mb4_unicode_ci 适用排序和比较规则场景
  • (转)ObjectiveC 深浅拷贝学习
  • (转)编辑寄语:因为爱心,所以美丽
  • (转载)跟我一起学习VIM - The Life Changing Editor
  • .gitignore文件忽略的内容不生效问题解决