B-Tree 漫谈 (从二叉树到二叉搜索树到平衡树到红黑树到B树到B+树到B*树)
2016-06-19 16:40
513 查看
关于B树的学习还是需要做点笔记。
B树是为磁盘或者其他直接存取辅助存储设备而设计的一种平衡查找树。B树与红黑树的不同在于,B树可以有很多子女,从几个到几千个。比如一个分支因子为1001,高度为2的B树,他可以存储超过10亿个关键字,尽管如此,因为根节点(只有一个)保留在主存中,故这可书中,寻找某一个关键字之多需要两次磁盘存取。
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/02/b16c197355d3a5469e236efc847e0c9f.png)
关于磁盘的结构,以及写入,读取数据的原理,这里就略过了。
一、概述:
1) 对于B树的每个节点x有:
a)n[x],当前存储在结点x中的关键字数,
b)关键字以非降序存放,因此 key1[x]<=key2[x]<=...<=keyn[x]
c) leaf[x],是一个布尔值,用来表示结点x是不是叶子节点。
2) 每个内结点包含n[x] + 1个指向其子女的指针 c1[x], c2[x], ... ,c (n[x]+1) [x]。当然叶节点没有c的定义。
3) keyi[x]对存储在各子树中的关键字范围加以分隔。
4) 每个叶节点具有相同的高度。
5)每个节点能包含的关键字数具有一个上界和一个下界。这些界可以用一个称作B树的最小度数的固定整数t >=2 来表示。
定理:h <= log t底 (n+1)/2。 证明略。详见 算法导论。
二、基本操作:
B树与搜索二叉查找树很相似,之时在每个节点所做的不是“二路选择”而是“根据子女数目做多路选择”。
1) 创建一棵空 B树:
首先创建一个空的根结点,再调用INSERT插入新的关键字。最后DISK-WRITE写入
2) 插入:
将新的节点插入到树中,当然是在不违反B树的有效性的前提下。那么如果新节点将要插入的节点y是一个满的叶节点,
故需要引入一个“分裂”操作,将该节点从中间的关键字keyt[y]分为两个各含t-1个关键字的节点。中间关键字被提升
到y的双亲结点。当然,如果y的双亲结点也是满的,那么就要保证在y做分裂操作之前就保证双亲已经通过分裂操作变得不满。
为了满足以上要求:当我们在由上向下查找当前新结点的归属时,就将沿途的满节点分裂,那么就可以保证每当要分裂一
个满结点y时,确保它的双亲不是满的。可以见得:树长高的唯一方式就是 分裂 根节点。
首先,创建一个新结点z, 然后将原来y节点中的 t ... 2t - 1 (t- 1)个关键字剪贴至新结点z,然后将中间关键字放入y的
父节点中。
对B树用单程下行遍历树方式插入关键字:
直接上图了吧。来自 --《算法导论》
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/02/6789d80f9bbb8181f34c05d04e94fb10.jpg)
一图胜千言啊。
4)删除操作
对于结点x递归调用B-Tree-Delete后,x的关键字个数至少等于最小度t。注意!这个要求比之前的要求(B树中最少关
键字个数t-1)多了一个,使得有时在递归降至某节点的一个子节点之前,一个关键字必须转移到子节点内。这个加强的条件
允许我们在一趟下降的过程中,就可以将一个关键字从树中删掉。
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/02/9e1eff4ad215657fff6c689b88330ceb.jpg)
删除操作稍微复杂一点。总结一下复杂度:对于一棵高度为h的B树,它只需要O(h)次磁盘存取操作。所需CPU时间为O(th) = O(tlogt n)。
B树是为磁盘或者其他直接存取辅助存储设备而设计的一种平衡查找树。B树与红黑树的不同在于,B树可以有很多子女,从几个到几千个。比如一个分支因子为1001,高度为2的B树,他可以存储超过10亿个关键字,尽管如此,因为根节点(只有一个)保留在主存中,故这可书中,寻找某一个关键字之多需要两次磁盘存取。
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/02/b16c197355d3a5469e236efc847e0c9f.png)
关于磁盘的结构,以及写入,读取数据的原理,这里就略过了。
一、概述:
1) 对于B树的每个节点x有:
a)n[x],当前存储在结点x中的关键字数,
b)关键字以非降序存放,因此 key1[x]<=key2[x]<=...<=keyn[x]
c) leaf[x],是一个布尔值,用来表示结点x是不是叶子节点。
2) 每个内结点包含n[x] + 1个指向其子女的指针 c1[x], c2[x], ... ,c (n[x]+1) [x]。当然叶节点没有c的定义。
3) keyi[x]对存储在各子树中的关键字范围加以分隔。
4) 每个叶节点具有相同的高度。
5)每个节点能包含的关键字数具有一个上界和一个下界。这些界可以用一个称作B树的最小度数的固定整数t >=2 来表示。
定理:h <= log t底 (n+1)/2。 证明略。详见 算法导论。
二、基本操作:
B树与搜索二叉查找树很相似,之时在每个节点所做的不是“二路选择”而是“根据子女数目做多路选择”。
1) 创建一棵空 B树:
首先创建一个空的根结点,再调用INSERT插入新的关键字。最后DISK-WRITE写入
2) 插入:
将新的节点插入到树中,当然是在不违反B树的有效性的前提下。那么如果新节点将要插入的节点y是一个满的叶节点,
故需要引入一个“分裂”操作,将该节点从中间的关键字keyt[y]分为两个各含t-1个关键字的节点。中间关键字被提升
到y的双亲结点。当然,如果y的双亲结点也是满的,那么就要保证在y做分裂操作之前就保证双亲已经通过分裂操作变得不满。
为了满足以上要求:当我们在由上向下查找当前新结点的归属时,就将沿途的满节点分裂,那么就可以保证每当要分裂一
个满结点y时,确保它的双亲不是满的。可以见得:树长高的唯一方式就是 分裂 根节点。
首先,创建一个新结点z, 然后将原来y节点中的 t ... 2t - 1 (t- 1)个关键字剪贴至新结点z,然后将中间关键字放入y的
父节点中。
对B树用单程下行遍历树方式插入关键字:
直接上图了吧。来自 --《算法导论》
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/02/6789d80f9bbb8181f34c05d04e94fb10.jpg)
一图胜千言啊。
4)删除操作
对于结点x递归调用B-Tree-Delete后,x的关键字个数至少等于最小度t。注意!这个要求比之前的要求(B树中最少关
键字个数t-1)多了一个,使得有时在递归降至某节点的一个子节点之前,一个关键字必须转移到子节点内。这个加强的条件
允许我们在一趟下降的过程中,就可以将一个关键字从树中删掉。
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/02/9e1eff4ad215657fff6c689b88330ceb.jpg)
删除操作稍微复杂一点。总结一下复杂度:对于一棵高度为h的B树,它只需要O(h)次磁盘存取操作。所需CPU时间为O(th) = O(tlogt n)。
相关文章推荐
- Fragment学习
- 如何最佳地使用memcached?
- 分布式消息中间件(七)——Kafka安装及配置详解(Linux)
- CSS 盒子模型
- HBase配置性能调优
- Python2.7网络爬虫---简单的爬取百度贴吧的小爬虫
- Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系
- ECMAScript6新特性简介
- CSS基础
- c++使用 STL string 实现split,trim和replace方法
- android:layout_weight的一点理解
- HBase设计与开发性能优化
- linux 下的nrf24l01成功的驱动,模拟spi
- 查看存储过程和函数
- 卡尔曼(Kalman)滤波(五)-- 三次样条插值
- 推荐系统算法(5)<InfoQ系列翻译文章,2016>
- EditText(第1章)-简介以及游标相关属性
- 关于IPMI的几个问题
- 客户端
- 调用存储过程和函数