<算法导论>高级数据结构--以我的角度看B树(Balanced-Tree)的建增删查
题外话:在博客园看了几篇关于B树的博文确实很有帮助,但是也看到有一些Funny的博文- -比如拿二叉树堂(BinaryTree)而皇之写上B树的帽子。
好了题归正传,B树(Balanced-Tree)与红黑树的主要不同在于,B树的节点可以有许多子女,从几个到几千个。这就是说,B树的分支因子可能会非常的大,这一分支因子往往又是由磁盘所决定的,B树与红黑树的相似之处在于,每棵含N个节点的B树的高度为O(lgn),但可能要比一棵红黑树的高度小很多,也就是意味着递归向下访问时的地址堆栈段可以节省一定的空间,因其分支因子比较大,所以B树也可以用来在O(logN)时间内,实现许多动态集合操作。
B树的几个必要的属性定义如下:
(1)首先是最重要的B树的度数,每一个B树的节点的关键字的个数不允许少于t-1个,也不允许大于2t-1个。个人讲不得不说设计B树的人实在是功夫高深,t-1和2t-1这一对神奇的数字正好构成了B树的完美分裂和合并过程。
(2)从数据结构的角度来讲,每一个B树节点的数据存储域在于一个保存关键字的个数n和一个保存子节点指针数组c[],另外一个重要的域是布尔值leaf用于表示该节点是否是一个内节点/根节点/叶结点。
一.B树的创建为以下几个步骤:
(a)在内存/进程堆中寻找一段空闲的空间来创建一个新的B树
(b)将该节点的leaf域置为true(该节点既是根节点也是叶结点),并且将n域置为0说明这是一个空的根节点,内部并没有关键字
(c)写入磁盘储存
二.B树的搜索过程(简单的递归过程,这里不多赘述)
三.B树的插入关键字过程分支步骤如下:
不妨假设访问某一个个节点的函数为(r,k)k为需要新加入的关键字
首先需要判断当前访问到的节点的关键字个数是否满足2t-1个
Y:对当前访问到的节点及进行一次分裂的操作,即将该满节点的中间序关键字提升,如果并没有父节点的话新创建一个父节点并且将其加入至新的节点,如果有父节点 的话即将该中间序关键字提升一个高度
N:直接进行遍历的向下递归访问插入操作,每向下访问一级都需要检查该节点是否为叶结点和关键字个数是否已经满,如果满节点的话再进行一次分裂中间序关键字提 升高度的操作,因为之前访问到的每一个节点都是经过了处理所以不会出现提升高度的关键字被插入关键字个数已经等于2t-1的父节点之中的情况。
四.B树的删除关键字过程步骤最为复杂:
假设需要删除的关键字k在于节点x中:
(1)当该节点是个叶结点的时候直接进行对k删除操作
(2)当该节点是个内节点的时候进行以下的分支操作:
a.如果该节点x的前于k的子节点y至少包含了t个关键字,则找出k在以y为根的子树的前驱k‘来代替删除的节点k
b.如果该节点x的后于k子节点z至少包含了t个关键字,则找出k在以y为根的子树的前驱k’‘来代替删除的节点k
c.如果该节点x的前后yz节点的关键字个数为t-1个的时候,将该关键字向下和前驱后继合并,再从该合并的节点之中删除该关键字
如果需要删除的关键字并不在当前访问到的节点之中,我们需要分支执行以下两个步骤来保证子树的根至少含有t个关键字
a.如果下一级需要访问的节点的只有t-1个关键字,但他的相邻兄弟子树节点含有至少t个关键字,则将父子树中的一个关键字降至下一步要访问的子树的关键字集之中,并且同时在相邻的兄弟子树节点的之中将一个关键字提升到父子树的关键字集之中。
b.如果下一步要访问的子树都只包含t-1个关键字,则将要访问的子树节点和一个兄弟节点合并,即将父子树中的一个关键字降至两个子树之间作为中间关键字,再进行删除操作。
///////////////Extra:What if 要删除的叶结点的个数不够t-1个了呢?