多路查找树(2-3 树、2-3-4 树、B 树、B+ 树)


本文参考自《大话数据结构》


计算机中数据的存储

一般而言,我们都是在内存中处理数据,但假如我们要操作的数据集非常大,内存无法处理了,在这种情况下对数据的处理需要不断地从硬盘等存储设备中调入或调出内存页面。

对外存设备的读写,效率并不乐观。为了降低对外存设备的访问次数,我们需要新的数据结构来处理这个问题。之前学习过的树,一个结点可以有多个孩子,但它自身只能存储一个元素。二叉树限制更多,只有两个孩子结点。在元素非常多时,要么树的度非常大(结点拥有子树的个数的最大值),要么树的高度非常大,如果我们要查找某一元素,必须多次访问外存设备,这迫使我们要打破每一个结点只能存储一个元素的限制,引入多路查找树的概念。

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


2-3 树和 2-3-4 树

2-3 树是拥有以下性质的多路查找树:

  • 每一个结点都具有两个孩子(称为 2 结点)获三个孩子(称为 3 孩子)

  • 一个 2 结点包含一个元素和两个孩子(或没有孩子),左子树包含的元素小于该元素,右子树包含的元素大于该元素

  • 一个 3 结点包含一大一小两个元素和三个孩子(或没有孩子),左子树包含的元素小于较小元素,右子树包含的元素大于较大元素,中间子树包含介于两个元素之间的元素

  • 2-3 树中所有的叶子结点都在同一层次上

对于 2-3 树,查找某一元素的方法与二叉排序树一样。要判断一个元素是否存在,我们先将待查找元素和根节点比较,如果它和其中任意一个相等,那查找命中;否则根据比较的结果来选择查找的方向。

要对 2-3 树插入元素,如果是一颗空树,直接创建一个 2 结点即可,如果不是空树,则要考虑以下情况:

  • 插入结点到一个 2 结点,可直接将 2 结点转换为 3 结点

  • 插入结点到一个 3 结点,其父结点为 2 结点

    如果命中查找结束于 3 结点,先临时将其成为 4 结点,把待插入元素添加到其中,然后将 4 结点转化为 3 个 2 结点,中间的结点成为左右结点的父结点,并与父结点为合并。

  • 插入结点到一个 3 结点,其父结点为 3 结点

    插入元素后一直向上分解临时的 4 节点,直到遇到 2 节点的父节点变成 3 节点不再分解为止。如果达到树根节点还是 4 节点,则分解根节点,此时树高加一(只有分解根节点才会增加树高)。

对于 2-3 树的删除,如果对前面插入的理解到位的话,就不是难事了。相比于插入,删除的情况较多,如果逐一介绍就太浪费时间了,总的来说它是有规律的。

2-3-4 树其实就是 2-3 树的概念扩展,它多了一个 4 结点。一个 4 结点包含小中大三个元素和四个孩子(或没有孩子),左子树包含小于最小元素的元素;第二子树包含大于最小元素,小于第二元素的元素;第三子树包含大于第二元素,小于最大元素的元素;右子树包含大于最大元素的元素。


B 树和 B+ 树

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

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

  • 如果根结点不是叶结点,则至少有两颗子树
  • 每一个非根的分支结点都有 k-1 个元素和 k 个孩子
  • 所有叶子结点都处于同一层次
  • 值位于 k-1 和 k 之间的子结点,都位于 k-1 和 k 对应的 value 之间

B 树的插入和删除和 2-3 树或 2-3-4 树是类似的,只不过阶数可能会很大而已。B 树可以帮助我们减少内存与外存之间数据的频繁交换,假设一颗 B 树的阶是 1001,高度为 2,它可以存储超过 10 亿个关键字。我们只要让根结点持久保留在内存中,那么寻找一个关键字至多只需要两次硬盘的读取。而如果使用二叉树,那就不得了了,光是树的高度就不知道比使用 B 大到哪里去,对硬盘的读取次数自然也多得多。

B 树还是有缺陷的,如果我们要遍历一颗 B 树,必须往返于每个结点之间,也就意味着得多次访问硬盘,有没有可能让遍历时每个元素只访问一次呢?我们在原有的 B 树结构基础上,加上新的元素组织形式,这就是 B+ 树。

B+ 树与 B 树的差异在于:

  • B+ 树的分支结点不保存关键字,只进行数据索引,结点中仅含有其子树中的最大(或最小)关键字
  • B+ 树所有的叶子结点包含全部关键字信息,及指向含这些关键字记录的指针,叶子结点本身依关键字的大小从小到大顺序链接

B+ 所有关键字数据地址都存在叶子节点上,所以每次查找的次数都相同,查询效率也比 B 树稳定。B+ 树也结点遍历速度更快,因为只需要从最左侧的叶子结点出发,一直沿着指向下一叶子结点的指针遍历即可。另外,B+ 树天然具备排序功能,因此特别适合带有范围的查找。


posted @ 2020-10-18 01:47  低吟不作语  阅读(1097)  评论(0编辑  收藏  举报