B树
简述
对于B树一直有博文说B树就是二叉搜索树,其实这种理解是错误的。
B树和B-树是同一种树,只不过英语中B-tree被中国人翻译成了B-树,让人以为B树和B-树是两种树。
实际上,两者就是同一种树,-是连字符而不是减号。
详情可以参见维基百科:B树定义。
概括来说,M阶B树就是一个节点可以拥有多于2个子节点的二叉查找树。
条件
一个M阶B树满足以下条件:
- 定义任意非叶子结点最多只有M个儿子,且M>2
- 根结点的儿子数为:[2, M]
- 除根结点以外的非叶子结点的儿子数为:[M/2, M]
- 每个结点存放的关键字数目为:[M/2-1, M-1],至少2个关键字
- 非叶子结点中,关键字个数=指向儿子的指针个数-1;
- 非叶子结点的关键字:K[1], K[2], …, K[M-1],且K[i] < K[i+1]
- 非叶子结点的指针:P[1], P[2], …, P[M];其中P[1]指向关键字小于K[1]的子树,P[M]指向关键字大于K[M-1]的子树,其它P[i]指向关键字属于(K[i-1], K[i])的子树
- 所有叶子结点位于同一层
图例
一棵3阶B树的示例图如下:
搜索
- 从根结点开始,对结点内有序的关键字序列进行二分查找,
- 如果命中则结束;否则进入查询关键字所属范围的儿子结点;
- 一直重复,直到所对应的儿子指针为空,或已经是叶子结点;
特性
- 关键字集合分布在整颗树中
- 任何一个关键字出现且只出现在一个结点中
- 搜索有可能在非叶子结点结束
- 其搜索性能等价于在关键字全集内做一次二分查找
- 自动层次控制
理念
- 保持键值有序,以顺序遍历
- 使用层次化的索引来最小化磁盘读取
- 使用不完全填充的块来加速插入和删除
- 通过优雅的遍历算法来保持索引平衡
B+树
简述
B+树是B-树的变体,也是一种多路搜索树。
B+树的特点是能够保持数据稳定有序,其插入与修改拥有较稳定的对数时间复杂度。
异同
B+树基本与B-树相同,除了:
- 非叶子结点的子树中,指针与关键字个数相同;
- 非叶子结点的子树指针P[i],指向关键字值属于[K[i], K[i+1])的子树,而B-树是(K[i], K[i+1]);
- 为所有叶子结点增加一个链指针;
- 所有关键字都在叶子结点出现;
图例
一棵3阶B+树的示例图如下:
特性
- 所有关键字都出现在叶子结点的链表中(稠密索引),且链表中的关键字恰好是有序的
- 不可能在非叶子结点命中
- 非叶子结点相当于是叶子结点的索引(稀疏索引),叶子结点相当于是存储(关键字)数据的数据层
- 更适合文件索引系统
B*树
简述
是B+树的变体,在B+树的非根和非叶子结点再增加指向兄弟的指针;
图例
一棵3阶B*树的示例图如下:
总结
B树:多路搜索树,每个结点存储M/2到M个关键字,非叶子结点存储指向关键字范围的子结点;
所有关键字在整颗树中出现,且只出现一次,非叶子结点可以命中;
B+树:在B树基础上,为叶子结点增加链表指针,所有关键字都在叶子结点中出现,
非叶子结点作为叶子结点的索引;B+树总是到叶子结点才命中;
B*树:在B+树基础上,为非叶子结点也增加链表指针,将结点的最低利用率从1/2提高到2/3;