B树(B-树)与B+树与红黑树

B树是为实现高效的磁盘存取而设计的多叉平衡搜索树。这个概念在文件系统,数据库系统中非常重要。当然,有关于B树的产生,发展,结构等等方面的介绍已经非常详细,所以本文只是介绍有关于B树和B+树最核心的知识点,也算是我本人的学习笔记。至于详细的资料,因为毕竟有着太多,所以不再赘述。可以向大家推荐一篇博客:从B树、B+树、B*树谈到R 树,这篇文章中,作者对于B树系列数据结构的讲解非常详细,我的这篇博客,也是大量参考了人家的很多例子和描述。

B树

一、基本原理

首先,其实b树和b-树是一个东西。开始我以为不一样。是因为B-Tree,可以把中间的-当破折号也可以当减号= =简单说一下B树产生的原因。B树是一种查找树,我们知道,这一类树(比如二叉查找树,红黑树等等)最初生成的目的都是为了解决某种系统中,查找效率低的问题。B树也是如此,它最初启发于二叉查找树,二叉查找树的特点是每个非叶节点都只有两个孩子节点。然而这种做法会导致当数据量非常大时,二叉查找树的深度过深,搜索算法自根节点向下搜索时,需要访问的节点也就变的相当多。如果这些节点存储在外存储器中,每访问一个节点,相当于就是进行了一次I/O操作,随着树高度的增加,频繁的I/O操作一定会降低查询的效率。

这里有一个基本的概念,就是说我们从外存储器中读取信息的步骤,简单来分,大致有两步:

  1. 找到存储这个数据所对应的磁盘页面,这个过程是机械化的过程,需要依靠磁臂的转动,找到对应磁道,所以耗时长。
  2. 读取数据进内存,并实施运算,这是电子化的过程,相当快。

综上,对于外存储器的信息读取最大的时间消耗在于寻找磁盘页面。那么一个基本的想法就是能不能减少这种读取的次数,在一个磁盘页面上,多存储一些索引信息。B树的基本逻辑就是这个思路,它要改二叉为多叉,每个节点存储更多的指针信息,以降低I/O操作数。

二、基本结构

1. B树的定义

有关于B树概念的定义,不同的资料在表述上有所差别。我在这里采用《算导》中的定义,用最小度tt tt来定义B树。一棵最小度为tt tt的B树是满足如下四个条件的平衡多叉树:

  • 每个节点最多包含2t−12t−1 2t - 12t−1个关键字;除根节点外的每个节点至少有t−1t−1 t - 1t−1个关键字(t≤2t≤2 t \leq 2t≤2),根节点至少有一个关键字;

  • 一个节点uu uu中的关键字按非降序排列:u.key1≤u.key2≤…u.keynu.key1≤u.key2≤…u.keyn u.key_1 \leq u.key_2 \leq \dots u.key_nu.key1​≤u.key2​≤…u.keyn​;

  • 每个节点的关键字对其子树的范围分割。设节点uu uu有n+1n+1 n + 1n+1个指针,指向其n+1n+1 n + 1n+1棵子树,指针为u.p1,…u.pnu.p1,…u.pn u.p_1, \dots u.p_nu.p1​,…u.pn​,关键字kiki k_iki​为u.piu.pi u.p_iu.pi​所指的子树中的关键字,有k1≤u.key1≤k2≤u.key2…k1≤u.key1≤k2≤u.key2… k_1 \leq u.key_1 \leq k_2 \leq u.key_2 \dotsk1​≤u.key1​≤k2​≤u.key2​…成立;

  • 所有叶子节点具有相同的深度,即树的高度hh hh。这表明B树是平衡的。平衡性其实正是B树名字的来源,B表示的正是单词Balanced;

一个标准的B树如下图:

2. B树的高度

我直接给出结论了:对于一个包含nn nn个关键字(n≥1n≥1 n \geq 1n≥1),最小度数t≥2t≥2 t \geq 2t≥2的B树T,其高度hh hh满足如下规律:

 

h≤logtn+12h≤logt⁡n+12

 

在搜索B树时,很明显,访问节点(即读取磁盘)的次数与树的高度呈正比,而B树与红黑树和普通的二叉查找树相比,虽然高度都是对数数量级,但是显然B树中loglog loglog函数的底可以比2更大,因此,和二叉树相比,极大地减少了磁盘读取的次数。

三、搜索算法

这里,我直接用博客从B树、B+树、B*树谈到R 树中的例子(因为这个例子非常好,也有现成的图示,就直接拿来用,不再自己班门弄斧了),一棵已经建立好的B树如下图所示,我们的目的是查找关键字为29的文件:

先简单对上图说明一下:

  • 图中的小红方块表示对应关键字所代表的文件的存储位置,实际上可以看做是一个地址,比如根节点中17旁边的小红块表示的就是关键字17所对应的文件在硬盘中的存储地址。

  • P是指针,不用多说了,需要注意的是:指针,关键字,以及关键字所代表的文件地址这三样东西合起来构成了B树的一个节点,这个节点存储在一个磁盘块上

下面,看看搜索关键字的29的文件的过程:

  1. 从根节点开始,读取根节点信息,根节点有2个关键字:17和35。因为17 < 29 < 35,所以找到指针P2指向的子树,也就是磁盘块3(1次I/0操作)

  2. 读取当前节点信息,当前节点有2个关键字:26和30。26 < 29 < 30,找到指针P2指向的子树,也就是磁盘块8(2次I/0操作)

  3. 读取当前节点信息,当前节点有2个关键字:28和29。找到了!(3次I/0操作)

由上面的过程可见,同样的操作,如果使用平衡二叉树,那么需要至少4次I/O操作,B树比之二叉树的这种优势,还会随着节点数的增加而增加。另外,因为B树节点中的关键字都是排序好的,所以,在节点中的信息被读入内存之后,可以采用二分查找这种快速的查找方式,更进一步减少了读入内存之后的计算时间,由此更能说明对于外存数据结构来说,I/O次数是其查找信息中最大的时间消耗,而我们要做的所有努力就是尽量在搜索过程中减少I/O操作的次数。

四、向B树插入关键字

向B树种插入关键字的过程与向二叉查找树中插入关键字的过程类似,但是要稍微复杂一点,因为根据上面B树的定义,我们可以看出,B树每个节点中关键字的个数是有范围要求的,同时,B树是平衡的,所以,如果像二叉查找树那样,直接找到相关的叶子,插入关键字,有可能会导致B树的结构发生变化而这种变化会使得B树不再是B树。

所以,我们这样来设计B树种对新关键字的插入:首先找到要插入的关键字应该插入的叶

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值