B 树英文是 B-Tree,所以中文的B树或者B-树都是同一个东西。至于其中的字母B,则不代表任何东西,既不是 Binary,也不是 Balance.
B 树是一种多路搜索树,对于一个 m-阶 的B树:
从定义中可以看出,B树和其它的平衡查找树的最大区别就是不再是一个二叉树,每个结点可以存放多个值(key),并且指向多个子结点。具体地说,一个结点中存放的数据结构为:(n,a0,K1,a1,K2,…,Kn,an),其中 n 代表这个结点含有的 key 的个数,Ki 代表存放的key(也就是二叉树中的value,比如2,23,57...),按升序排列,ai 则是指向子结点的指针,并且 ai 指向的子结点中存放的 key 值总是大于 ai 左边的 key 小于 ai 右边的 key(注意是开区间)。比如a1指向的子结点中存放的元素一定介于K1和K2之间。
B树比起平衡搜索树更加矮胖,这样做大大减小了树的高度,在B树中插入时,B树的高度也会增长得很缓慢,因为每一层都可以容纳很多元素。在最好的情况下,每个结点都被填满,即存放了 m - 1 个元素,最好情况下,B 树的高度为:
最坏情况下,每个结点只有 d = ⌈m/2⌉ 个子结点,B树的高度为:
由于B树在高度方面有很大优势,因此,对于文件系统以及数据库,B树是一个不错的选择。在这类应用中,磁盘IO的时间已经远远超过了读取到数据之后在内存中进行处理的时间,所以提升速度的关键是减小磁盘IO。如果每读一次结点,都要进行一次磁盘IO,那当然是希望尽量减少读结点的次数,即使在B树种读了一个结点之后会需要在内存中进行多次比较(一个结点里面有很多元素),那样也会快得多。
关于B树,推荐阅读:B-tree - Wikipedia
B树的查找类似于二叉搜索树的查找,在每个结点,找到待查找元素在哪个范围之间,再进入对应的子结点继续比较
插入元素的时候,先找到元素应该插入的位置,此时:
如果该结点存放的元素数量还没有超过最大限制,那么直接将该元素插入该结点
如果该结点已经满了,那就将其分裂(Split)为两个结点:
这个网站提供了B树的可视化操作:BTree Visualization
参考:
B+ 树是B 树的变种。广泛用于各种文件系统和数据库引擎中。B+ 树的定义与B树基本相同,不同的地方在于: