目录
下一篇:查找之B+树
一、将二叉查找树拓展为m叉
//5叉排序树的结点定义
struct Node{
ElemType key[4];//最多4个关键字
struct Node *child[5];//最多5个汉字
int num;//结点中有几个关键字
};
每个分叉就是一个查找范围
紫色为失败结点
查找一个元素
查找失败的例子:
如何保证查找效率
1、若每个结点关键字太少,导致树变高,要查找更多层结点,效率变低
注:是向上取整
例如5叉就除了根结点外,任何结点都至少有3个分叉,2个关键字
2、不平衡的多叉查找树也会降低效率
满足1、2两点则就是B树
二、B树定义:
记住:核心特性
三、求B树最小高度(每个结点尽可能的填满)
注:这里的高度不包含叶子结点
𝑛≤𝑚−11+𝑚+𝑚2+…+𝑚h−1
可得
四、求最大高度
那么除了根结点只有两个分叉外,其他的都是[m/2]向上取整个分叉
可推算共有第一层1个结点,第二层2个、第三层2[m/2]个+第四层2[m/2]^2个……第h层2[m/2]^(h-2)个结点
则叶子结点(失败结点)一共
2𝑚2h−1个结点
补充重要特性:
n个关键字的B树和二叉排序树一样,相当于在
−∞,+∞间插入了n个数字
这些数字将这个区间分成了n+1个小区间
即n个关键字的B数一定有n+1个失败结点(叶子结点)
即n+1>=2𝑚2h−1
另外一种算法
小结1:
五、B树的插入
示例:
5阶B树插入(每个结点关键数大于等于2小于等于4,分叉大于等于3小于等于5)
当根结点插入到达上限
从中间位置([m/2]向上取整)分裂成两个结点,并形成新的根结点
现在插入90,通过查找来判断插入到哪个位置,且一定是终端结点的位置
若不是终端位置
会导致叶子结点不在同一层,不满足B树
当某个结点又满了
同样将其[m/2]位置的元素即88提到父结点中(父结点指向该满了的结点的指针的右边的位置)
通过不断的插入后
父结点也超出上限
父结点分裂导致树高+1
六、B树的删除
当前树
若删除上面的60这个元素,这是个终端结点,且删除后关键字个数并没有低于2
若删除根结点的元素
如删除根的80,若用直接前驱代替则找到其左子树最右下的元素(类似于二叉排序树),若采用直接后继代替则找到根节点右子树最左下位置的元素,转化成终端结点元素的删除
若被删除所在结点的关键字个数低于下限
如下图删除25右边的元素后
则把25的后继放到25的右边,把后继的后继放到49的位置
即:
借左兄弟的例子:
删除90
显然右兄弟不够了,左兄弟够
87代替父结点中88的位置,88放到92的左边
当兄弟们都不够借时就进行合并
例如:
将兄弟两合并,为了保持大小关系还要把父结点上的70拿下来放在25左边
发现父结点不够了,且借不了则再次合并,把父结点中的元素82拿下来
合并后:
最后删除空的结点,合并的结点成为新的根结点