B树、B+树

when ? why ? how ? what ?

平衡二叉树其查找的时间复杂度是 O(log2N)与树的深度相关,那么降低树的深度自然会提高查找效率。

如果我们要操作的数据集非常大,大到内存已经没法处理了怎么办呢?如数据库中的上千万条记录的数据表、硬盘中的上万个文件等。在这种情况下,对数据的处理需要不断从硬盘等存储设备中调入或调出内存页面。

一旦涉及到这样的外部存储设备,关于时间复杂度的计算就会发生变化,访问该集合元素的时间已经不仅仅是寻找改元素所比较次数的函数,我们必须考虑硬盘等外部存储设备的访问时间以及将会对该设备做出多少次单独访问

我们从外存储器中读取信息的步骤,简单来分,大致有两步:

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

为什么需要 B 树?

在一个拥有几十万个文件的磁盘中查找一个文本文件,你设计的算法需要读取磁盘上万次还是读取几十次,这是有本质差异。此时,为了降低对外存设备的访问次数,我们就需要新的数据结构(B 树)来处理这样的问题

之前谈的树,都是一个结点可以有多个孩子,但它自身只存储一个元素。二叉树限制更多,结点最多只能有两个孩子。

问题来了? 在元素非常多的时候,要么树的度非常大(结点拥有子树的个数的最大值),要么树的高度非常大,甚至两者都必须足够大才行。这就使得内存存取外存次数非常多,这显然成了时间效率上的瓶颈,这迫使我们要打破每一个结点只存储一个元素的限制,为此引入了多路查找树

多路查找树

什么是多路查找树?

多路查找树(muitl-way search tree),其每一个结点的孩子数可以多于两个,且每个结点出可以存储多个元素。由于它是查找树,所有元素之间存在某种特定的排序关系。

B 树

B 树是一种平衡的多路查找树,2-3树和2-3-4树都是 B 树的特例。结点最大孩子的数目称为 B 树的阶(order),因此,2-3 树是 3 阶 B 树,2-3-4 树是 4 阶 B 树 。

一个 m 阶的 B 树具有如下属性:

  1. 如果根结点不是叶结点,则其至少有两棵子树
  2. 每一个非根的分支结点都有 k-1 个元素和 k 个孩子,其中 ⌈m/2⌉ <= k <=m
  3. 所有的叶子节点都位于同一层
  4. 所有分支结点包含下列信息数据(n,A0,K1,A1,K2,A2….,Kn,An),其中:Ki(i=1,2,3,…n)为关键字,且 Ki < Ki+1(i=1,2,….,n-1);Ai(i=0,2,….n)为指向子树根结点的指针,且指针 Ai-1 所指子树中所有结点的关键字均小于 Ki(i=1,2,….,n),An所指子树中所有结点的关键字均大于 Kn,n(⌈m/2⌉-1<= n <=m-1)为关键字的个数(或n+1为子树的个数)。

2-3-4树

下图灰色方块表示当前结点元素的个数。

《B树、B+树》

如果内存和外存交换数据次数频繁,会造成了时间效率上的瓶颈,那么 B 树结构怎么就可以做到减少次数呢?

外存比如硬盘,是将所有的信息分割成相等大小的页面,每次硬盘读写的都是一个或多个完整的页面,对于一个硬盘来说,一页的长度可能是 211 或 214 个字节。

在一个典型的 B 树应用中,要处理的硬盘数据量很大,因此无法一次全部装入内存。因此我们会对 B 树 进行调整,使得 B 树的阶数 (或结点的元素)与硬盘存储的页面大小匹配。比如一棵 B 树的阶位 1001(即一个结点包含 1000 个关键字),高度为 2,它可以存储超过 10 亿个关键字,我们只要让根结点持久地保留在内存中,那么在这棵树上,寻找某一个关键字至多需要两次硬盘的读取即可。

通过这种方式,在有限内存的情况下,每一次磁盘的访问我们都可以获取最大数量的数据。由于 B 树每结点可以具有比二叉树多得多的元素,所以与二叉树的操作不同,它们减少必须访问结点和数据块的数量,从而提高了性能。可以说,B树的数据结构就是为内外存的数据交互准备的。

对于有n个关键字的m阶B-树,从根结点到关键字所在结点的路径上路过的结点数不超过:

《B树、B+树》

B+树

为什么会产生 B+ 树呢?

肯定是 B 树有些缺陷,有些需求然后就产生的 B+ 树。

《B树、B+树》

如上图的 2-3 树,要是你想查找 3~11 范围的元素,中序遍历 页面 5 -> 页面 2 ->页面 6 -> 页面 1 ->页面 7,查找很麻烦,看看 B+树

《B树、B+树》

当找到查找下限 3 后,通过链表指针可以查找到 11,这样会快很多。

在 B 树中,每一个元素在该树中只出现一次,有可能在叶子结点上,也有可能在分支结点上。而在 B+ 树中,出现在分支结点中的元素会被当作它们在该分支结点位置的中序后继者(叶子结点)中再次列出。另外,每一叶子结点都会保存一个指向后一叶子结点的指针。

卫星数据:指的是索引元素所指向的数据记录,比如数据库中的某一行。

B+ 树的特征:

  1. 有 k 个子树的中间结点包含有 k 个元素(B 树中是 k-1 个元素),每个元素不保存数据,只用来索引,所有数据都保存在叶子节点。(在B 树中,无论中间结点还是叶子结点都带有卫星数据)
  2. 所有的叶子结点包含了全部元素的信息,及指向含这些元素的记录的指针,且叶子结点本身依关键字的大小自小而大顺序连接。
  3. 所有的中间结点元素都同时存在余子节点,在子节点元素中是最大(或最小)元素。

B+ 树的优势
1. B+ 树的中间结点没有卫星数据。所有以同样大小的磁盘可以容纳更多结点元素,这就意味着,数据量相同的情况下,B+ 树的结构比 B- 树更加“矮胖”,因此查询是 IO次数也更少。
2. B- 树查找性能不稳定(最好情况只查根结点,最坏情况查到叶子结点),而B+ 树每次查找都是最稳定的。
3. 所有叶子节点形成有序链表,便于范围查询。如查找学小18~22岁的学生人数,我们可以通过根结点触发找到第一个18岁学生,然后再在叶子结点按顺序查找到符合范围的所有记录

总结

参考

大话数据结构

https://www.sohu.com/a/156886901_479559

B树是为实现高效的磁盘存取而设计的多叉平衡搜索树。这个概念在文件系统,数据库系统中非常重要。数据库中的索引就用了B树或B+树。

有什么问题欢迎指出,十分感谢!

    原文作者:B树
    原文地址: https://blog.csdn.net/u013164931/article/details/81171299
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞