1 B树
1.1 一颗m阶B树的定义
- 每个结点最多有m-1个关键字。
- 根结点最少只有1个关键字。
- 非根结点至少有Math.ceil(m/2)-1个关键字。注:Math.ceil()是取上界的意思
- 每个结点中的关键字都按照从小到大的顺序排列,每个关键字的左子树中的所有关键字都小于它,而右子树中的所有关键字都大于它。
所有叶子结点都位于同一层,或者说根结点到每个叶子结点的长度都相同。
1.2 B树的插入/删除
https://www.cnblogs.com/nullzx/p/8729425.html
1.3 采用B树而不采用二叉搜索树的原因
事实上,搜索过程中,B树的比较次数并不比二叉搜索树少,尤其是单一节点中元素个数比较多时。
但是,B树的深度低于二叉搜索树,因此查询时经过的节点数量比二叉搜索树少。在查询时,每到一个新的节点都对应了一次I/O操作,与I/O耗时相比,比较耗时可以忽略。因此,B树的I/O操作少,查询时间更短。
2 B+树
2.1 B+树与B树最大的不同
内部结点不保存数据,只用于索引,所有数据(或者说记录)都保存在叶子结点中。
2.2 一颗m阶的B+树定义
- B+树包含2种类型的结点:内部结点(也称索引结点)和叶子结点。根结点本身即可以是内部结点,也可以是叶子结点。根结点的关键字个数最少有1个。
- m阶B+树表示了内部结点最多有m-1个关键字(或者说内部结点最多有m个子树),阶数m同时限制了叶子结点最多存储m-1个记录。
- 内部结点中的key都按照从小到大的顺序排列,对于内部结点中的一个key,左树中的所有key都小于它,右子树中的key都大于等于它。叶子结点中的记录也按照key的大小排列。
每个叶子结点都存有相邻叶子结点的指针,叶子结点本身依关键字的大小自小而大顺序链接。
2.3 B+树的插入/删除
https://www.cnblogs.com/nullzx/p/8729425.html
2.4 B+树比B树更适合作文件索引/数据库索引
- 不同于B树只适合随机检索,B+树同时支持随机检索和顺序检索;
- B+树的磁盘读写代价更低。B+树的内部结点并没有指向关键字具体信息的指针,其内部结点比B树小,盘块能容纳的结点中关键字数量更多,一次性读入内存中可以查找的关键字也就越多,相对的,IO读写次数也就降低了。而IO读写次数是影响索引检索效率的最大因素。
- B+树的查询效率更加稳定。B树搜索有可能会在非叶子结点结束,越靠近根节点的记录查找时间越短,只要找到关键字即可确定记录的存在,其性能等价于在关键字全集内做一次二分查找。
而在B+树中,随机检索时任何关键字的查找都必须走一条从根节点到叶节点的路,所有关键字的查找路径长度相同,导致每一个关键字的查询效率相当。 数据库索引采用B+树的主要原因:
- B树在提高了磁盘IO性能的同时并没有解决元素遍历的效率低下的问题。
- B+树的叶子节点使用指针顺序连接在一起,只要遍历叶子节点就可以实现整棵树的遍历。而且在数据库中基于范围的查询是非常频繁的,而B树不支持这样的操作。
2.5 补充:B*树
在B+树的非根和非叶子结点增加了指向兄弟的指针B*树是B+树的变种,相对于B+树他们的不同之处如下:
- 首先是关键字个数限制问题,B+树初始化的关键字初始化个数是cei(m/2),B树的初始化个数为(cei(2/3m)),即块的最低使用率为2/3。
- B+树节点满时就会分裂;而B*树结点满时会先检查兄弟结点是否满(每个结点都有指向兄弟的指针)如果兄弟结点未满,则向兄弟结点转移关键字,然后在原结点插入新的关键字,最后修改父结点中兄弟结点的关键字(因为兄弟结点的关键字范围改变了);
如果兄弟结点已满,则在原结点与兄弟结点之间增加新结点,并从当前结点和兄弟结点各拿出1/3的数据到新的结点中,最后在父结点中增加新结点的指针。
特点:
- 与B+树相比,其非根结点初始化的容量变大(cei(2/3*m)),使得结点的空间使用率更高;
- 因为存有兄弟结点的指针,可以向兄弟结点转移关键字,使得B*树的分裂(分配新结点)概率更低;
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。