码迷,mamicode.com
首页 > 其他好文 > 详细

B树、B-树、B+树、B*树

时间:2015-04-22 18:21:24      阅读:131      评论:0      收藏:0      [点我收藏+]

标签:

声明:本文只是介绍了这几种树的定义和相互之间的比较介绍。并没有涉及到它们的插入、删除、分裂、整合等操作。这些会在后面的文章中有介绍。


B 树

即二叉搜索树:

   1.所有非叶子结点至多拥有两儿子(Left和Right);
   2.所有结点存储一个关键字;
   3.非叶子结点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树;

如:

技术分享

B树的搜索,从根结点开始,如果查询的关键字与结点的关键字相等,那么就命中;
否则,如果查询关键字比结点关键字小,就进入左儿子;如果比结点关键字大,就进入右儿子;
如果左儿子或右儿子的指针为空,则报告找不到相应的关键字;

如果B树的所有非叶子结点的左右子树的结点数目均保持差不多(平衡),那么B树的搜索性能逼近二分查找;
但它比连续内存空间的二分查找的优点是: 改变B树结构(插入与删除结点)不需要移动大段的内存数据,甚至通常是常数开销;

技术分享

B树在经过多次插入与删除后,有可能导致不同的结构:

技术分享

右边也是一个B树,但它的搜索性能已经是线性的了;同样的关键字集合有可能导致不同的树结构索引;所以,使用B树还要考虑尽可能让B树保持左图的结构,和避免右图的结构,也就是所谓的“平衡”问题;

实际使用的B树都是在原B树的基础上加上平衡算法,即“平衡二叉树”;如何保持B树结点分布均匀的平衡算法是平衡二叉树的关键;平衡算法是一种在B树中插入和删除结点的策略;

B-树

是一种多路搜索树(并不是二叉的):

1) 每个节点 x 有下面属性:
 - 节点 x 有关键字 n 个
 - 关键字本身非降序排列
 - 有一个布尔值表示本节点是否是叶子节点
2)每个内部节点x 还包含 n+1 个指向孩子的指针
3)每个叶节点具有相同的深度
4)每个节点包含的关键字个数有上界和下界, 使用B树的最小度数 t >=2 表示
- 除根节点外每个节点必须至少有 t-1 个关键字,因此,每个内部节点至少有 t 个孩子
- 每个节点最多包含 2t-1 个关键字,因此, 一个内部节点最多有 2t 个孩子。

t =2 时是最简单的。每个内部节点有2、3、4个孩子。即一颗2-3-4树。

如 (M=3):

技术分享

技术分享
B-树的搜索,从根结点开始,对结点内的关键字(有序)序列进行二分查找,如果

命中则结束,否则进入查询关键字所属范围的儿子结点;重复,直到所对应的儿子指针为

空,或已经是叶子结点;

B-树的特性:

       1.关键字集合分布在整颗树中;
       2.任何一个关键字出现且只出现在一个结点中;
       3.搜索有可能在非叶子结点结束;
       4.其搜索性能等价于在关键字全集内做一次二分查找;
       5.自动层次控制;

B+树

B+-tree:是应文件系统所需而产生的一种B-tree的变形树。

一棵m阶的B+树和m阶的B树的异同点在于:

  1. n棵子树的结点中含有n 个关键字;
  2. 所有的叶子结点中包含了全部关键字的信息,及指向含有这些关键字记录的指针,且叶子结点本身依关键字的大小自小而大的顺序链接。 (而B 树的叶子节点并没有包括全部需要查找的信息)
  3. 所有的非终端结点可以看成是索引部分,结点中仅含有其子树根结点中最大(或最小)关键字。 (而 B 树的非终节点也包含需要查找的有效信息)

技术分享

上图中非终端节点中仅包含子树根节点中最小关键字的指针。

为什么说B+-tree比B 树更适合实际应用中操作系统的文件索引和数据库索引?

  1. B+-tree的磁盘读写代价更低

B+-tree的内部结点并没有指向关键字具体信息的指针。因此其内部结点相对B 树更小。如果把所有同一内部结点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多。一次性读入内存中的需要查找的关键字也就越多。相对来说IO读写次数也就降低了。

举个例子,假设磁盘中的一个盘块容纳16bytes,而一个关键字2bytes,一个关键字具体信息指针2bytes。一棵9阶B-tree(一个结点最多8个关键字)的内部结点需要2个盘快。而B+ 树内部结点只需要1个盘快。当需要把内部结点读入内存中的时候,B 树就比B+ 树多一次盘块查找时间(在磁盘中就是盘片旋转的时间)。
2. B+-tree的查询效率更加稳定

由于非终结点并不是最终指向文件内容的结点,而只是叶子结点中关键字的索引。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当。
3. 数据库索引采用B+树的主要原因是:

B树在提高了磁盘IO性能的同时并没有解决元素遍历的效率低下的问题。正是为了解决这个问题,B+树应运而生。B+树只要遍历叶子节点就可以实现整棵树的遍历。而且在数据库中基于范围的查询是非常频繁的,而B树不支持这样的操作(或者说效率太低)

B*-tree

B*-treeB+-tree的变体,在B+树的基础上(所有的叶子结点中包含了全部关键字的信息,及指向含有这些关键字记录的指针),B*树中非根和非叶子结点再增加指向兄弟的指针B*树定义了非叶子结点关键字个数至少为(2/3)*M,即块的最低使用率为2/3(代替B+树的1/2)。给出了一个简单实例,如下图所示:

技术分享

B+树的分裂:当一个结点满时,分配一个新的结点,并将原结点中1/2的数据复制到新结点,最后在父结点中增加新结点的指针;B+树的分裂只影响原结点和父结点,而不会影响兄弟结点,所以它不需要指向兄弟的指针。

B*树的分裂:当一个结点满时,如果它的下一个兄弟结点未满,那么将一部分数据移到兄弟结点中,再在原结点插入关键字,最后修改父结点中兄弟结点的关键字(因为兄弟结点的关键字范围改变了);如果兄弟也满了,则在原结点与兄弟结点之间增加新结点,并各复制1/3的数据到新结点,最后在父结点增加新结点的指针。

所以,B*树分配新结点的概率比B+树要低,空间使用率更高;

B树、B-树、B+树、B*树

标签:

原文地址:http://blog.csdn.net/yapian8/article/details/45196743

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!