B树设计的原因
B树出现是因为磁盘IO。IO操作的效率很低,那么,当在大量数据存储中,查询时我们不能一下子将所有数据加载到内存中,只能逐一加载磁盘页,每个磁盘页对应树的节点。造成大量磁盘IO操作(最坏情况下为树的高度)。平衡二叉树由于树深度过大而造成磁盘IO读写过于频繁,进而导致效率低下。
所以,我们为了减少磁盘IO的次数,就你必须降低树的深度,将“瘦高”的树变得“矮胖”。
PS:这里我找到了一个讲述很好的二叉树与B树的比较链接。大家可以阅读以下。
http://m.elecfans.com/article/662237.html
比如下面图片
二叉树以2为最大基准向下延伸,而B树则没有标准,所以它可以变得矮矮胖胖的。
B树的定义
B 树又叫平衡多路查找树。一棵m阶的B 树 (m叉树)的特性如下:
- B树中所有节点的孩子节点数中的最大值称为B树的阶,记为M(重点)
- 树中的每个节点至多有M棵子树 —即:如果定了M,则这个B树中任何节点的子节点数量都不能超过M
- 若根节点不是终端节点,则至少有两棵子树
- 除根节点和叶节点外,所有点至少有m/2棵子树(上溢)
- 所有的叶子结点都位于同一层。(比如上面的图片中我没有了11 13 15,那么我12就没有存在的意义了,就需要调整整个树的布局)
总结: 1、树中一个结点最多有m个子节点。而这个m称为B树的阶。2树中节点最少要2个(叶子节点除外)
B树的查找操作
在B树上进行查找和二叉树的查找很相似,二叉树是每个节点上有一个关键字和两个分支。B树上每个节点有K个关键字和K+1个分支。二叉树的查找只考虑向左还是向右走,而B树中需要由多个分支决定。
B树的查找分两步,首先查找节点,由于B树通常是在磁盘上存储的所以这步需要进行磁盘IO操作。第二步是查找关键字,当找到某个节点后将该节点读入内存中然后通过顺序或者折半查找来查找关键字。若没有找到关键字,则需要判断大小来找到合适的分支继续查找。
看了上面一大堆的描述,感觉还是看不懂,没关系,接下来直接举个例子
如下有一个3阶的B树,观察查找元素21的过程:
第一次磁盘IO:
首先进行IO操作,找到根节点后,将该节点读入内存中,然后通过顺序或者折半查找来查找关键字21。由于根节点没有21这个元素,所以没有找到关键字,则需要判断大小来找到合适的分支继续查找。21<32,且这里只有 两个分支,所以从左分支进行接下来的查找。
第二次磁盘IO:
和上一步操作一样。
首先进行IO操作,找到左节点(第二节点)后,将该节点读入内存中,然后通过顺序或者折半查找来查找关键字21。由于左节点没有21这个元素,所以没有找到关键字,则需要判断大小来找到合适的分支继续查找。21>3&&21>12,所以从最右边的分支进行接下来的查找。
这里有一次内存比对:分别跟3与12比对。
第三次磁盘IO:
和上一步操作一样,最后找到21
由于B树相对于二叉树来说矮胖了许多,所以它所涉及的IO操作也相对少了许多。不过根据我们上面的分析,其在查找数据的时候并没有减少比较次数。但是我们知道,我们在比较数据的时候是在内存中进行的,所以相对来说时间上会更加迅速,几乎可以忽略。
而相同数量的key在B树中生成的节点要远远少于二叉树中的节点,相差的节点数量就等同于磁盘IO的次数。这样到达一定数量后,性能的差异就显现出来了。
参考: https://www.jianshu.com/p/a858bb15cbf0
一下为天勤数据结构里面关于B树定义、查找的讲解,个人觉得将的很好,可以参考。(第一、二张图片看不懂直接看第三张图片)