B树
前面讨论过的数据结构都是在内存中完成操作的,
因此考虑的都是内存中的时间复杂度,
但是如果要操作的数据非常之大,如数据库中的千万条数据表,
硬盘中的上亿个文件时,对数据的处理就需要不断地从外存调入,调出。
一旦涉及外存,关于时间复杂度的计算就会发生改变,
访问该集合元素的时间,已经不仅仅是 寻找该元素所需比较次数的函数,
我们必须考虑对 外存设备的访问时间以及将会对该设备做出多少次单独访问。
实际上,为了降低对外存的访问次数,我们选 :B树
多路查找:每一个节点可以储存多个元素,可以有多个孩子。
一:2-3树
特点:每一个节点都具有两个孩子(2节点) 或三个孩子(3节点)
一个2节点包含一个元素数据 和 两个孩子(或没有孩子)
一个3节点包含一大一小两个数据元素和三个孩子(或者没有孩子)
亦符合 排序树 的规则
并且 2-3 树的所有叶子结点 都在同层。
插入 ↓
核心思想:
1、始终保持排序树:也就是遵循 中序遍历的 大小次序。
2、升级降级:在 2 节点 升级成 3 节点。也有可能一部分节点在由3节点降成 2 节点。
3、合理拆分:3 节点 合理的按照终须遍历的顺序拆分成 2 节点。
4、适当延伸:当 3 真的不能满足要求时,适当增加一层树的深度。
*
*
*
*
删除节点
** 对于 位于 一个 3 节点的叶子节点上,很简单只需要直接删除 ↓ :
**对于所要删除的元素 位于一个 2 节点上的情况(即 要删除的是只有一个元素的节点),直接删除是不行的。
分四种情况讨论:
1、此节点的双亲也是 2 节点。而拥有一个 3 节点的右孩子。
删除 1 后左旋 ↓ :
2、此节点的双亲是 2 节点,双亲的右孩子也是 2 节点 。
如果强行删除节点4,如果,需要对整棵树进行变形。办法就是:目标是让节点7 变成一个“3 节点”那就让8下来,9上去。于是有了中间图。再左旋,变成右图 ↓ 。
3、节点的双亲是一个3 节点。
若删除10,双亲12/14不能成为“3节点”了,于是将此节点拆分:并将 12 /13 合并成为左孩子 ↓ 。
4、如果当前树是一个满二叉树。
此时删除任何一个叶子都会使得整棵树不能满足 2- 3 树的定义,这时候就需要考虑层数的减少了哈 ↓ 。。
*
*
*
*
*
**对于所要删除的元素位于 非叶子 的分支节点,我们通常是将树按照中序遍历的方式得到此元素的前驱后继,考虑让他们来补位即可。下图6/7是一个“3 节点”,就用她俩来补位~
如果我们要删除的是”3节点”的某一元素,如下图 节点12,这个找12 的前驱更合适。
———————————-以上列举了几种以供参考。
*
*
*
*
*
*
2 - 3 - 4 树
“4节点” 包括 小、中、大 三个数据域元素 和四个孩子(要么四个孩子,要么没有孩子),仍是中序排列:
如 : 构建一个 { 7,1,2,5,6,9,8,4,3 } 树:
图一:最多有三个数据域元素,从 节点5 开始拆分:
删除过程:
*
*
——-——————————————我是分割线——————————————–
***********************B树*****************************
B树是一种平衡的多路查找树,2-3树 和 2-3-4 树 是他的特例,
最大拥有的最大孩子数叫做B树的阶,
2-3是3阶树,2-3-4 是4阶树。
一个 m 阶树 具有如下属性:
1、根结点至少有两个子女;
2、每个非根节点所包含的关键字个数 j 满足:┌m/2┐ - 1 <= j <= m - 1;
3、除根结点以外的所有结点(不包括叶子结点)的度数正好是关键字总数加1,故内部子树个数 k 满足:┌m/2┐ <= k <= m ;
4、所有的叶子结点同层。
————————— baidu 百科。