简介:
B-tree(也就是B树,多路搜索树,并不是二叉的)是一种常见的数据结构。使用B-tree结构可以显著减少定位记录时所经历的中间过程,从而加快存取速度。
B+-树使用广泛,一般用于数据库的索引,综合效率较高。
B-树是Rudolf Bayer, Edward M. McCreight(1970)写的一篇论文《Organization and Maintenance of Large Ordered Indices》中首次提出的。(wikipedia:http://en.wikipedia.org/wiki/B-tree)
They were designed to work well on Direct Access secondary storage devices (magnetic disks). B-trees try to read as much information as possible in every disk access operation.
磁盘读取数据是以盘块(block)为基本单位的。位于同一盘块中的所有数据都能被一次性全部读取出来。而磁盘IO代价主要花费在查找时间Ts上。因此我们应该尽量将相关信息存放在同一盘块,同一磁道中。或者至少放在同一柱面或相邻柱面上,以求在读/写信息时尽量减少磁头来回移动的次数,避免过多的查找时间Ts。
所以,在大规模数据存储方面,大量数据存储在外存磁盘中,而在外存磁盘中读取/写入块(block)中某数据时,首先需要定位到磁盘中的某块,如何有效地查找磁盘中的数据,需要一种合理高效的外存数据结构,就是下面所要重点阐述的B-tree结构,以及相关的变种结构:B+-tree结构和B*-tree结构。
B树与红黑树最大的不同在于,B树的结点可以有许多子女,从几个到几千个。那为什么又说B树与红黑树很相似呢?因为与红黑树一样,一棵含n个结点的B树的高度也为O(lgn),但可能比一棵红黑树的高度小许多,应为它的分支因子比较大。所以,B树可以在O(logn)时间内,实现各种如插入(insert),删除(delete)等动态集合操作。
一个B树的例子:21个英文辅音字母:
*每个内部节点x包含n(x)个key和n(x)+1个子节点
*所有叶子拥有同样的高度
*节点x的n(x)个key按非递减顺序存储(key1<=key2<=……keyn)
*假设ki为Ci子树key,有:(结合上面的例子理解)
上面说了B树是多路搜索树,那么对于M阶的B树,它必须满足以下条件:
1.对于root,要么是一个叶子,要么含有[2,M]个儿子
2.非叶子节点必须有[ceil(M/2),M]个儿子(ceil表示向上取)
3.所有叶子拥有同样的高度
4.每个内部节点x包含n(x)个key和n(x)+1个子节点
下面用K[]代表key,P[]代表指向子树的指针,有:
如这样:
让我们来看一个5阶B树:根据定义,每个节点至多有5个子节点和4个key,非root节点至少有3个子节点和2个key.
B树操作:
1)插入(在看下面插入过程时,时刻记住B tree需要满足的条件,你就大概知道为什么这么做了)
1.2插入H
1.3 插入EKQ
1.4 插入M
1.5 插入FWLT
1.6 插入Z
1.7 插入D
1.8 插入S
总结起来就是:
(1)对于未满的节点直接插入;
(2)对于已满节点,按照类似插入排序方式插入,并将该节点围绕中心节点拆分成两个节点;
(3)将中心节点上移到父节点;
(4)如父节点也满了,重复上述(2)操作。
2)删除
2.1 删除H
2.2 删除T
2.3 删除R
2.4 删除E
2.5 G不满足条件,合并
总结起来就是:
(1)若叶子节点未空(这里的空指已是最少节点),直接删除;
(2)若叶子节点已空,则要与兄弟合并(合并意味着父节点要减少),因此删除后将父节点下移再合并,若父节点下移后为空,删除后可以向丰满(>ceil(M/2))子节点借一节点或向上迭代此过程;
(3)对于非叶子结点,若节点为空而子节点丰满(>ceil(M/2)),删除后向子节点借一节点;若子节点也为空,则合并子节点并向上迭代此过程;