有了BST和AVL树,为什么还需要B+树?
我们在讨论BST、AVL树等等这些时基于这样一个假设 即可以把整个数据结构存储到计算机的主存中。 但是,当数据多到主存装不下时,那么就必须把数据结构放到磁盘上了,此时大O模型不再适用。
大O分析基于的假设是所有操作耗时都是相等的。
那又如何呢?还是不知道B+树有何用武之地。且慢,听我细细分解。举一个例子,一台500-MIPS机器每秒执行五亿条指令,因为它是电驱动的;而磁盘操作基于机械运动,一个7200RPM,即一分钟7200转,的磁盘,相当于1转1/120秒,即8.3毫秒。这和处理器的速度比起来简直慢到不可理喻,这也意味着磁盘访问的代价太高了! 与此同时,处理器的速度还比磁盘的速度增长快得多,两者差距越来越大。因此,为了节省一次磁盘访问我们愿意写一个复杂的程序。
但出路绝不是二叉查找树!
典型的AVL树已接近最优高度,由二叉查找树我们不可能低于logN。由直觉,出路已呼之欲出,如果有更多的分支,那么就会有更低的高度,即构造M叉树(M>2)。一棵完全二叉树的高度约为log2N,而一棵完全M叉树的高度约为logMN。此外,正如为了防止BST退化为链表我们引入平衡条件一样,为了防止M叉查找树退化为二叉查找树,我们也会引入一些条件。总之,B+树首先是一棵M叉查找树。
B+树的定义
阶为M的B+树是一棵具有以下特性的树:
1.所有数据存储在叶子节点上。
2.非叶子节点存储到M-1个关键字以指示搜索方向,第 i 个key值等于子树 i + 1 中的最小值。
3.树的根或者是一个叶子节点,或者其儿子数在2和M之间(包括2)。
4.除根外,所有非叶子节点的儿子树在 [M/2向上取整] 和 M 之间。
5.所有叶子节点都在相同深度上,并有 [L/2向上取整] 和 L 之间个数据。
关于L和M,其实应该是L可以等于M但非必需(《数据结构与算法分析 Java语言描述》P102-103),但国内大多默认L=M,这里暂且取L=M,关于L的确定书中有具体给出。
关于B+树的阶数是许多刚接触的同学会搞混的地方,只要看最多允许有几个叶子节点即可,注意这里是允许不是必须,比如定义是一棵5阶B+树,即使倒数第二层每一个节点都只有4个叶子节点,这仍是一棵5阶B+树。或者看每一个非叶子节点最多允许存放的关键值个数,M阶B+树最多允许非叶子节点有M-1个关键值。前后两种判断其实是一致的只是角度不同。
B+树的插入,删除
先留链接为敬 B树自在人心
相关面试题
1. B+树相对于B树有什么优点?
(1)B+树的所有数据都存储在叶子结点上,非叶子结点只起到索引作用。而在B树中每个结点的每个关键字都存储数据。在相同数据量下,B+树更加矮胖,磁盘IO开销更少。
(2)B树查找性能不稳定,最好情况是查到根结点,最坏情况是查到叶子结点。而B+树每次必查到叶子结点,性能稳定。
(3)B+树所有叶子结点形成有序链表,便于范围查询。
参考资料:
1.《数据结构与算法分析 Java语言描述》第三版