标签:
声明:本文只是介绍了这几种树的定义和相互之间的比较介绍。并没有涉及到它们的插入、删除、分裂、整合等操作。这些会在后面的文章中有介绍。
即二叉搜索树:
1.所有非叶子结点至多拥有两儿子(Left和Right);
2.所有结点存储一个关键字;
3.非叶子结点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树;
如:
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+-tree
:是应文件系统所需而产生的一种B-tree
的变形树。
一棵m
阶的B+
树和m
阶的B
树的异同点在于:
n
棵子树的结点中含有n
个关键字;B
树的叶子节点并没有包括全部需要查找的信息)B
树的非终节点也包含需要查找的有效信息)上图中非终端节点中仅包含子树根节点中最小关键字的指针。
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+-tree
的变体,在B+
树的基础上(所有的叶子结点中包含了全部关键字的信息,及指向含有这些关键字记录的指针),B*
树中非根和非叶子结点再增加指向兄弟的指针;B*
树定义了非叶子结点关键字个数至少为(2/3)*M
,即块的最低使用率为2/3(
代替B+
树的1/2
)。给出了一个简单实例,如下图所示:
B+
树的分裂:当一个结点满时,分配一个新的结点,并将原结点中1/2
的数据复制到新结点,最后在父结点中增加新结点的指针;B+
树的分裂只影响原结点和父结点,而不会影响兄弟结点,所以它不需要指向兄弟的指针。
B*
树的分裂:当一个结点满时,如果它的下一个兄弟结点未满,那么将一部分数据移到兄弟结点中,再在原结点插入关键字,最后修改父结点中兄弟结点的关键字(因为兄弟结点的关键字范围改变了);如果兄弟也满了,则在原结点与兄弟结点之间增加新结点,并各复制1/3
的数据到新结点,最后在父结点增加新结点的指针。
所以,B*
树分配新结点的概率比B+
树要低,空间使用率更高;
标签:
原文地址:http://blog.csdn.net/yapian8/article/details/45196743