标签:防止 现在 平衡 指针 watch 例子 方式 线段 nal
关键字 1-2 个
子节点 2-3 个
平衡树:子节点的高度一致
一种平衡的多分树
平衡:所有的叶结点在同一层,所以每个子节点的高度一致
1、每个结点至多有m个子结点
2、除根节点和叶节点外,其他每个结点至少有m/2(向上取整)个结点
3、根结点至少有两个子结点
4、所有的叶结点在同一层(平衡)
5、有k个子节点的非根节点恰好包含k-1个关键码
1、树高平衡,所有叶结点都在同一层
2、关键码没有重复,父结点中的关键码是其子结点的分界
3、B树把(值接近)相关记录放在同一个磁盘页中,从而利用局部性原理
4、B树保证树中至少有一定比例的结点是满的(每个结点有至少有m/2个子节点,半满)
B树的一个包含j个关键码,j+1个指针的节点的一般形式为:
P0,K1,P1,K2,P2....Kj,Pj #j个关键码,j+1个指针指向子节点
其中ki是关键码值,K1<K2<….<Kj
Pi是指向Ki到Ki+1之间的关键码的子树的指针
class BNode{
int n;//子节点的个数
BNode<Key> *parent;//指向父节点的指针(可有可不有)
Key key[MAXREC];//存储关键码的数组,最多有MAXREC个关键码
BNode<Key> *ptr[MAXREC+1];//指向子节点的指针,最多有MAXREC+1个指针
}
1、把根节点读出来,在根节点所包含的关键码K1…Kj中查找给定的关键码值。当关键码不多时,就用顺序检索,当节点包含的关键码较多时,可以用二分检索。如果找到则检索成功
2、否则,确定要查的关键码指在某个Ki和Ki+1之间,那么去Pi所指向的节点继续查找
下图为查找24的过程
如果树高为h,则查找时访问外存的次数是h
注意:
每个关键码表示索引,找到索引后,每个关键码还对应一个指向外存的指针,这样通过索引才可以访问到完整的记录
情况1:
首先判断关键码14是否存在,按照图中的轨迹查找,此时到15所在的节点,遍历后发现没有14,则在该节点中插入
此时外存读的次数是3,写的次数是1
情况2:
插入可能导致B树朝着根的方向生长,即当插入位置超过关键字的最大个数,节点需要进行分裂
如插入55,但2-3树要求关键字数只由1~2个,此时插入节点50,52已经达到个数,55无法直接插入,需要进行分裂
50 52 55如何拆分?
父节点需要增加一个节点进行区分子节点拆分后的节点,采用二分的方法,将中间的52送到父节点,得到结果:
此时读的次数3,写的次数3(申请两个节点,并分别写入,这里包含两次写,还有在父节点中写入1次)
情况3:
多次分裂,树向上生长
最终的结果是:
6阶B树删除45
对于6阶B树,子节点树要求m/2~m,即 3~6,关键码的个数为2~5,在删除的过程中需要防止下溢出,即关键码的数量小于规定的个数
在删除掉45后,当前节点只有110一个关键字,下溢出了。其中一种方案是向左右节点借关键码,同时要将父节点拉下来,这里演示向右节点借关键码。此时合并的关键码有110,112,135,143,212,需要进行分裂,根据二分分裂的方式,将135移到父节点,即用135替换123,然后子节点分裂,反别是110,112和142,212,结果是:
给出一个极限情况下删除的例子:
删除的时候如果发生下溢出,即当前关键码个数小于定义的个数,则需要进行合并,向左节点或有节点合并
如果删除后,节点为0仍保持0的状态,按照向左向右合并的方式进行操作
B+树是B树的一种变形,是在叶结点上存储信息的树:
如下3阶B+树,节点最多有3个关键码,当插入15后,查询到10 23这个节点,插入15。父节点不需要重写
3阶B+树插入16后,叶子节点的关键为16超过最大阶3,所以需要分类成10、15和16、23,并增加分类节点之间的线性链接,修改父节点的关键码,每个关键码是子结点关键码最大值的复写
多次分裂
如下B+树删除23,首先需要查找23;第一个节点判断,23<=35,到第二个子结点查找;23<=23,在第一个子结点中查找;删除关键码23;
此时父节点中的23能够正确标识父节点的区间,所以不进行更新(类似线段树中的延迟更新)
节点结构:
查找:
B树每个节点保存了指向真实位置的指针,找到关键码就能找到真实位置;B+树必须索引到叶子节点;B+树提供了索性查找和顺序查找两种方式
实际中使用B+树特别多
第10章 索引——2(B树,B树) 标清
https://www.youtube.com/watch?v=vBD6Ve8VryY
原文:大专栏 5、B数、B+数、红黑树
标签:防止 现在 平衡 指针 watch 例子 方式 线段 nal
原文地址:https://www.cnblogs.com/petewell/p/11611846.html