B树和B+树

676 阅读4分钟

B树

B-Tree 是一颗多路平衡查找树,广泛用于磁盘访问。

  • 当数据量比较庞大的时候,我们需要将其存放在磁盘中,数据以块的形式从磁盘中读取。与内存的访问时间相比,磁盘的访问时间非常长。使用 B 树的的思想是想减少磁盘访问的次数。

  • 大多数树操作(搜索、插入、删除、最大值、最小值、..等)需要 O(h) 次磁盘访问,其中 h 是树的高度。B树是一棵"胖"树。通过在 B 树节点中放置最大可能的键,B 树的高度保持在较低水平。从而减少访问磁盘的次数。

下面是一个最小阶数为5的B-Tree的例子。注意,在实际的B-Trees中,最小阶数的值远远大于5。

m 阶B树有以下特性:

  1. 每个节点最多包含m-1个key,m个子节点。
  2. 根节点最少包含1个key,2个子节点。
  3. 非根节点至少包含m/2个key。
  4. 每个节点中的key都按照从小到大的顺序排列。
  5. 所有叶子节点都位于同一层。

注意:key (又:关键字),在上图B树的示意图中,画出来的数字就是key,我们在执行查找等操作时,正式依赖key帮我们锁定具体的节点。 同时,在B树中,节点除了包含key之外,还存储了子节点的指针和数据指针(数据索引)

B树节点示意图:

B+树

B+ Tree 是 B Tree 的扩展,它可以更高效的执行插入、删除和搜索操作

  • 在 B 树中,内部节点和叶节点中包含key和数据索引。而在 B+ 树中,只有叶子节点上包含数据索引,而内部节点只能存储key。这样的设计是的B+树的内部节点可以存储更多的key,有助于降低树的高度,从而减少磁盘访问次数。

  • B+树的叶节点以单链表的形式链接在一起,使搜索查询更有效率。

从上面我们也可以看出来,B+树中内部节点和叶子节点结构有所不同,下面详细了解一下。

B+树的内部节点结构如下:

  1. 每个内部节点的结构为:<p 1 , k p 2 .....> 其中 P i 是子节点指针,K i 是 key
  2. 其中:K 1 < K 2 < ...
  3. 对于 P1 所指向的子节点,key 值均小于 k1;对于 P2 所指向的子节点,key 值均大于 k1,小于 k2;依次类推。

如图:

B+树的叶子节点结构如下:

  • 每个叶节点的结构为: <<k 1 , d>, <k 2 , d>, ....., <k c-1 , d>, P next >

D i 是数据指针(即指向磁盘中键值为 K i 的实际记录或指向包含该记录的磁盘文件块),K i是 key,P next 指向下一个叶子节点。

  • 其中:K 1 < K 2 < ...。< K c-1
  • 所有叶节点都在同一层。

> 使用P next指针可以像链表一样遍历所有的叶子节点,从而实现对存储在磁盘中的记录的有序访问。

如图:

然后,将内部节点和叶子节点结合到一起。

B+树的示意图:

B树和 B+树的区别

最后总结一下两者的区别:

B树B+树
1所有内部和叶节点都有数据指针只有叶节点有数据指针
2由于并非所有键都在叶子上可用,因此搜索通常需要更多时间。所有键都在叶节点,因此搜索更快更准确。
3树中不存在重复的key存在重复的key
4插入删除比较复杂插入删除相对简单
5叶节点之间不存在指针叶节点之间不存在指针

最后:

相比之下,由于B+树的内部节点可以存储更多的key,书的高度也更低,所以磁盘读写代价更小;由于B+树的所有数据指针存储在叶子节点,每次查询都需要从根节点到叶子节点,查询长度相同,所以查询效率也更加稳定;同时,叶子节点指针的存在,这样B+树仅通过叶子指针就可以访问到所有数据,使得在数据扫描、区间查找方面代价更小。综上,B+树更加适用于数据库索引。

水平有限,文中如有错误还望指出。