原文:
https://www.nowcoder.com/discuss/27739?type=2&order=1&pos=30&page=2
B树、B+树、存储模型
参考:
http://www.cnblogs.com/yangecnu/p/Introduce-B-Tree-and-B-Plus-Tree.html
B树/多叉平衡查找树:
背景:
B树是为磁盘设计的多路平衡搜索树。一个B树节点通常和一个完整的磁盘页一样大,每次查询的结点深度(根节点其实永久保存在主存中)即为I/O操作的次数。由于其分支因子大,故其优势是降低磁盘I/O操作次数
二叉树的存储能力有限,当元素过多时,树的深度过大,退化为节点内部线性查找,查询效率低下。
为了降低树的深度,采用多叉树,多叉平衡查找树应运而生,即B树(B-tree树即B树,B即Balanced,平衡的意思)。
B树的各种操作能使B树保持较低的高度,从而达到有效避免磁盘过于频繁的查找存取操作,从而有效提高查找效率)。
减少IO操作是效率提升的关键。
M阶B树:
- 根结点至少有两个孩子
- 每个结点至多有M个孩子
- 除了根结点和叶结点,每个结点至少有[M/2]个孩子:孩子个数:[M/2]~M
- 除了根结点,每个结点的关键字个数n必须满足:[M/2]-1<= n<=M-1
- 所有叶子结点出现在同一层
- 位于m-1和m key的子节点的值位于m-1 和m key对应的Value之间
[*]为向上取整
B树插入操作:
B树的插入在叶结点,当结点空间满了,则分裂为两个相邻结点,中间关键字上移到父节点中。
若父节点也满了,同样分裂并上移,
直至根节点,若根节点也满了,则中间元素上移到新的根结点中,树的深度增加一层。
B树删除操作:
先删除:
- 若没有左右孩子结点,则直接删除,否则将孩子结点中相近的结点上移到当前节点中。
然后调整平衡性:
若某节点元素小于[M/2]-1,则:
– 若相邻兄弟元素大于[M/2]-1,从相邻兄弟借一个元素
– 若相邻兄弟元素小于等于[M/2]-1,则合并两结点
B+树:
B+树将所有卫星数据都存放在叶结点中,内部结点只存放关键字和孩子指针,因此最大化了内部结点的分支因子。且所有的叶子结点和相连的节点使用链表相连,便于范围查找和遍历。
有n棵子树的结点中含有n个关键字; (而B树是n棵子树有n-1个关键字)
所有的叶子结点中包含了全部关键字的信息,及指向含有这些关键字记录的指针,且叶子结点本身依关键字的大小自小而大的顺序链接。(而B树的叶子节点并没有包括全部需要查找的信息)
所有的非终端结点可以看成是索引部分,结点中仅含有其子树根结点中最大(或最小)关键字。 (而B 树的非终节点也包含需要查找的有效信息)
B+ 树的优点在于:
由于B+树在内部节点上不好含数据信息,因此在内存页中能够存放更多的索引信息,查询所需的IO次数减少。
数据存放的更加紧密,具有更好的空间局部性。因此访问叶子几点上关联的数据也具有更好的缓存命中率。B+树的叶子结点都是相链的,因此对整棵树的遍历只需要一次线性遍历叶子结点即可。而且由于数据顺序排列并且相连,所以支持范围查询和搜索。而B树则需要进行每一层的递归遍历。相邻的元素可能在内存中不相邻,所以缓存命中性没有B+树好。