概述
B树(B-Tree
)是一种自平衡的树,能够保证数据有序.同时它还保证了在查找、插入、删除等操作时性能都能保持在$O(log\;n)$.需要注意的一点是,B-Tree
并不是一棵自平衡的二叉查找树,它拥有多个分叉,且为大块数据的读写操作做了优化,同时它也可以用来描述外部存储(支持对保存在磁盘或者网络上的符号表进行外部查找).
在当今的互联网环境下,数据量已经大到无法想象,而能够在巨型数据集合中快速地进行查找操作是非常重要的,而B-Tree
的神奇之处正在于: 只需要使用4~5个指向一小块数据的引用即可有效支持在数百亿甚至更多元素的符号表中进行查找和插入等操作.
B-Tree
的主要应用在于文件系统与数据库系统,例如Mysql
中的InnoDB
存储引擎就使用到了B-Tree
来实现索引.
本文作者为: SylvanasSun.转载请务必将下面这段话置于文章开头处(保留超链接).
本文转发自SylvanasSun Blog,原文链接: https://sylvanassun.github.io/2017/08/13/2017-08-13-BTrees/
数据表示
我们使用页来表示一块连续的数据,访问一页的数据需要将它读入本地内存.一个页可能是本地计算机上的一个文件,也可能是服务器上的某个文件的一部分等等.页的访问次数(无论读写)即是外部查找算法的成本模型.
首先,构造一棵B-Tree
不会将数据保存在树中,而是会构造一棵由键的副本组成的树,每个副本都关联着一条链接.这种方法能够将索引与符号表进行分离,同时我们还需要遵循以下的规定:
- 选择一个参数
M
来构造一棵多向树(M
一般为偶数),每个节点最多含有M - 1
对键和链接.
- 每个节点最少含有
M / 2
对键和链接,根节点例外(它最少可以含有2对).
- .使用
M
阶的B-Tree
来指定M
的值,例如: 在一棵4阶B-Tree
中,每个节点都含有至少2对至多3对.
B-Tree
含有两种不同类型的节点,内部节点与外部节点.
- 内部节点含有与页相关联的键的副本: 每个键都与一个节点相关联(一条链接),以此节点为根的子树中,所有的键都大于等于与此节点关联的键,但小于原内部节点中更大的键(如果存在的话).
- 外部节点含有指向实际数据的引用: 每个键都对应着实际的值,外部节点就是一张普通的符号表.
|
|
查找
在B-Tree
中进行查找操作每次都会结束于一个外部节点.在查找时,从根节点开始,根据被查找的键来选择当前节点中的适当区间并根据对应的链接从一个节点移动到下一层节点.最终,查找过程会到达树底的一个含有键的页(也就是外部节点),如果被查找的键在该页中,查找命中并结束,如果不在,则查找未命中.
|
|
插入
插入操作也要先从根节点不断递归地查找到合适的区间,但需要注意一点,如果查找到的外部节点已经满了怎么办呢?
解决方法也很简单,我们允许被插入的节点暂时”溢出”,然后在递归调用自底向上不断地进行分裂.例如:当M
为5时,根节点溢出为6-节点
,只需要将它分裂为连接了两个3-节点
的2-节点
.即将一个M-
的父节点k
分裂为连接着两个(M / 2)-
节点的(k + 1)-
节点.
|
|