IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 查找树(四):B-树和B+树 -> 正文阅读

[数据结构与算法]查找树(四):B-树和B+树

1. 磁盘I/O问题

众所周知,相较于计算机指令的执行速度,访问磁盘所带来的开销是十分巨大的。对于一段需要访问磁盘的程序,程序运行的时间几乎都花费再了磁盘的I/O上。 也就是说,在这种情况下,如果我们可以将磁盘的访问次数减少一般,那么程序的运行时间也将减半。

当数据量较少,可以完全存储在内存时,数据的访问相对来说是比较快的,类似AVL树红黑树等数据结构可以将操作数据的时间复杂度控制在O(log2N)。当数据量很大时,无法将其存储在内存当中,只能退而求其次,存储在磁盘中;由于磁盘I/O速度的限制,此时大O模型将不再适用,磁盘的I/O次数决定了程序的时间成本。

针对数据被存储在磁盘中的情况,常规的平衡二叉树已经不能很好的满足我们的需求。因此,我们需要一种新的查找树结构,这种新的树结构可以在相同数据量时拥有更低的高度(树的高度决定了数据操作的最大访问次数)。

2. B-树

为降低树的高度,很自然的一个想法就是让树有更多的分支,B-树就遵循了此想法——既然一个节点有两个分支不够,那就让它拥有尽可能多的分支。B-树的所有节点都携带数据(这也是它和B+树的主要区别),由于它是一颗查找树,因此需要一个“排序”的依据,将此排序的依据成为关键码,每个关键码都关联着具体的数据元素。也就是说,节点的关键码个数也代表着节点存储的数据元素的个数。

B-树又被称为B树,B代表Balanced,即平衡的意思。一棵M阶的B-树有如下的特点:

  1. 根节点或是一片叶子,或是拥有 2 到 M 个个孩子;
  2. 除根外,所有非叶子节点都包含k-1个关键码和k个孩子,其中 ceil(M/2) <= k <= M(ceil表示向上取整,如ceil(2.5) = 3);
  3. 每一个叶子节点都包含k-1个关键码,其中 ceil(M/2) <= k <= M;
  4. 所有的叶子结点都位于同一层;
  5. 每个节点中的关键码都遵循从小到大的排列,节点中的k-1个关键码正好可以划分出k个孩子。

单纯的看B-树的定义显得比较的抽象,可以通过具体的插入和删除操作进一步的理解B-树的结构。

2.1 B-树的插入操作

简单的来说,B-数的插入操作可以分为以下几种情况:

  • 插入后不破坏B-树规则,则直接插入;
  • 插入后该节点的关键码个数超出规定范围(M-1),则进行分裂操作;
  • 分裂操作后相当于父节点插入了一个新元素,递归的向上执行插入逻辑。

以M = 5为例(即一颗5阶的B-树),图例中蓝色代表新插入的元素,绿色代表插入前就已经存在的元素:

  1. 向空树中插入2(插入根节点):
    在这里插入图片描述
  2. 继续依次插入1、10、3(找到合适的位置插入即可),可以看到根节点中的关键码遵循从小到大的排列
    在这里插入图片描述
  3. 继续插入9后,此时根节点的关键码个数增加到5个(大于M-1),需要执行分裂操作(找到位于中间的关键码,进行拆分),分裂后根节点与其子树均符合B-树的特性:
    在这里插入图片描述
  4. 继续插入18、12、44,又一叶节点的关键码达到5个,继续分裂,中间元素被“上提”到父节点
    在这里插入图片描述

查找树的插入操作一般都会选择将新元素作为叶子节点插入,每次插入后,如果没有破坏B-树的规则,则插入结束;如果破坏了B-树的规则(插入操作中主要指关键码个数超出规定),则向进行分离操作,然后递归的检查父节点是否符合B-树的规则

2.2 B-树的删除操作

一般来说,删除操作都会比插入操作更加的复杂,B-树也是如此。简单的来说B-树的删除可以分为以下几种情况:

  • 被删除的关键码位于叶子节点,且删除后不破坏B-树规则,则直接删除;
  • 被删除的关键码位于叶子节点,删除后该节点关键码个数小于ceil(M/2)-1,则根据其兄弟节点的关键码个数,执行借关键码(兄弟节点的关键码足够)或合并(兄弟节点的关键码不足)操作;
  • 合并叶子节点后,父节点的关键码-1,相当于删除了内部节点的关键码,递归的执行删除逻辑即可;
  • 被删除的关键码位于内部节点,则根据该关键码的左右子节点的关键码个数,执行借关键码(子节点的关键码足够)或合并(子节点的关键码不足)操作;类似的,合并后递归的向上执行删除逻辑。

继续以M = 5为例,首先构造了一颗元素“较多”的B-树,然后对其进行删除操作,被删除的元素被表示为红色:

  1. 构造了一颗5阶的B-树:
    在这里插入图片描述
  2. 删除3,由于被删除的关键码存在于叶子节点,且删除后关键码个数符合B-树的规则,因此可以直接删除:
    在这里插入图片描述
  3. 删除25,删除后该叶子节点的关键码数为1,小于ceil(M/2)-1,此处需要根据其兄弟节点是否有足够的关键码(大于等于ceil(M/2)),有则向兄弟节点借一个,没有则进行合并操作。显然该节点的右兄弟存在足够的关键码,因此只需要向兄弟节点“借“一个关键码即可(父节点下移一个关键码,兄弟节点上移一个关键码):
    在这里插入图片描述
  4. 删除98,删除后面临和3中类似的情况,不同的是该叶子节点的兄弟节点没有足够的关键码可以借给它。此时,需要将该节点、该节点的兄弟节点以及父节点对应的关键码进行合并。合并操作会让父节点的关键码-1(相当于内部节点删除了一个元素),如果合并后父节点的关键码数不足,则递归的执行内部节点的删除操作
    在这里插入图片描述
  5. 删除31,被删除关键码所处的节点为内部节点,从内部节点中删除关键码首先需要观察“关键码对应的左右子节点”是否有足够的关键码,有则向子节点借一个,没有则进行合并。显然,此时31的右子节点有足够的关键码:
    在这里插入图片描述
  6. 删除31,删除后面临和5中类似的情况,不同的是此时子节点没有足够的关键码,因此执行合并操作。合并后父节点关键码-1,递归的向上执行删除逻辑:
    在这里插入图片描述

3. B+树

B+树是B-树的变体,也是一种多路搜索树,它与B-树类似,并规定了:

  • 非叶子节点不保存指向数据的指针,只进行数据索引(简单的来说就是只存放关键码,不保存数据);
  • 为所有叶子结点增加了一个链指针;
  • 内部节点中一个关键码对应一个子节点(B-树中子节点个数比关键码个数多1),关键码是子节点中最大(或最小)的元素。

也就是说,B+树的数据都被保存在了叶子节点中,为什么要这么做呢?

回顾引入B-树的过程,选取B-树的初衷是为了降低树的高度,以减少磁盘I/0的次数。一般来说,树的每一个节点都对应着一个磁盘区块,节点中存储元素的大小限制了节点存储元素的个数,即影响了最终所获的树的高度,从而影响磁盘I/O的次数。 B-树中的每个节点都保存着关键码和指向数据的指针,它们共同构成了前面所说的“元素”,如果可以减小元素的大小,就可以进一步的降低树的高度。

由于多路查找树的增删查操作都依赖于关键码,因此关键码是必须保留的,但数据指针在查找过程中却不是必须的,因此可以只保存在叶子节点中。B+树就是遵循了此原理,它的内部节点只保存了关键码(以及子节点的索引),不保存数据指针,所有的数据都被保存在了叶子节点中:

  • 使B+树获得更低的高度,从而减少磁盘I/O的次数
  • 由于数据都存储在叶子节点中,且叶子节点都位于同一层,所以查找操作是稳定的(每一次查找都需要相同的次数);
  • 同时,因为所有叶子节点形成了一个有序链表,范围查询变得更加便利了。

下面给出了一个B+树了示例:
在这里插入图片描述

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-09-12 20:44:24  更:2021-09-12 20:44:46 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/17 11:11:24-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码