B树的出现原因
首先,平衡二叉树的查找效率是非常高的,并可以通过降低树的深度来提高查找的效率,在数据量小的时候,平衡二叉树还是一种比较好的选择。但是当数据量非常大,必然会导致平衡二叉树的深度过大,内存可能装不下这颗二叉树,此时可以采用外部查找【在计算机中,存储器的层次结构一般分为:CPU寄存器、主存、辅存, [1] 外部查找是指在辅助设备空间进行数据查找。如在计算机中内存的大小是有限的, 如果要查找的数据量太大,无法全部加载到内存中,必须借助辅助存储设备的空间再进行查找。】,这时虽然存储问题解决了,但查询时读写辅助存储设备如磁盘I/O的速度的问题就凸显出来了,怎么尽量弥补这个缺陷呢?思路是尽量减少外部IO读写次数。
仔细查看二叉树,它的每一个节点其实都是对有序数据序列的二分段–每个节点都把一个数据序列分为两段,那有人就提出能不能一个节点把一个数据序列分为多个段而不仅仅是两个段呢?这样不就可以减小树的深度以及减少查询时对外部存储设备的磁盘读写IO次数了吗?在1970年,R.Bayer和E.mccreight提出了一种适用于外部查找的树,它是一种平衡的多叉树,称为B树(进一步还有B-树、B_树)。
注意B树的应用场景是数据量巨大,以至于不得不采用外部查找。
B树
1,B-Tree是多叉平衡查找树,"B"表示balance–平衡;
2,我们描述一颗B树时需要指定它的阶数,阶数表示了一个结点最多有多少子结点,一般用字母m(M)表示阶数,称m是B树的阶数 ,其中 m>=3。(为何要求m>=3,因为当m取2时,就是我们常见的二叉搜索树啦!)
B树定义
- 任意非叶子节点最多有M个分支 (M>2)
- 根节点的分支数为 [2,M]
- 分支节点的儿子数 [M//2,M]
- 每个节点至少存放 M / 2(向上取整),至多存放 M -1 个检索关键字
- 非叶子节点关键字数 = 分支数 - 1
- 非叶子节点关键字满足 k[1] < k[2]
- 非叶子节点指针 p[1]指向节点的关键字小于k[1]
- 所有叶子节点在同一层,且叶子节点值数量小于节点关键字数量
B+ 树
1. 基本与B树相同
除了:
2. 非叶子节点的子树关键字会包含父节点关键字
3. 在叶子节点中增加了链式结构用于串联所有的叶子
4. 所有关键字都一定会在叶子节点出现
相对于B树
1. 所有的关键字都子叶子中,数据更加稠密,使用链表将叶子串联
2. 不可能在非叶子节点中命中关键值
3. 更适合文件系统的索引
优点 : IO次数减少
查询稳定性更好
更适合范围查找