B树

B树是一种平衡多叉树,适用于外查找。其每个节点包含一组指针指向记录地址,保证结点半满。文章介绍了B树的特性、搜索过程、插入和删除操作,强调了B树在数据过大无法一次性加载内存时,对于磁盘查找的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 B树是一种适合与外查找的的搜索树,他是一种平衡的多叉树。在B树的每个结点中包含一组指针recptr[M]指向实际记录的存放地址。key[i]与recptr[i]形成一个索引项,通过key[i]可以找到某个记录的存储地址recptr[i]。

M阶的B树具有以下特点:
1、根节点要么是叶子结点,要么至少具有两个孩子。
2、非根结点(叶结点除外)都具有[M/2,M]个孩子。
3、非根结点都具有[M/2-1,M-1]个关键码,关键码以升序排列。
4、key[i]和key[i+1]之间的结点的值都介于key[i]与key[i+1]之间
5、数据项都保存在叶子结点中,且叶子结点都在同一层。


M/2是向上取整。
  B树的搜索过程是在一个结点内搜索和循某一条路径向下一层搜索交替进行的过程,因此B树的搜索时间与B树的阶数M(决定内部搜索次数)和B树的高度h有关。在B树上进行搜索,搜索成功的时间取决于关键码所在的层次,搜索不成功取决于树的高度。

  当数据太大,不能一次放入内存中,磁盘存取的数目就变成关键了。这时候我们就要使用外查找。B树是用于磁盘级查找最流行的数据结构。在B树中结点必须是半数填满的,这就保证了树不会退化成一颗简单的二叉树。


B树的插入:
  首先我们要在B树中寻找这个关键码,如果已经存在则插入失败,如果不存在又分为以下两种情况:
  1、如果要插入的叶子结点中的关键码的个数小于M-1,则直接插入,然后再重新组织叶子结点中的数据项。
  2、如果要插入的叶子结点中的关键码的个数就是M-1,表示叶子结点已满,这时候我们就要经这片叶子分裂为两片叶子。

实现分裂的原则是:
设结点p中已经有了M-1个关键码,当再插入一个关键码后结点中的状态为
(m,p0,k1,p1,k2,p2,k3,....,km,pm)
因为关键码的个数必须是在[M/2-1,M-1]之间,所以我们必须将p分裂为两个叶子结点p,q。
p:([m/2]-1,p0,k1,p1,....,k[m/2]-1,p[m/2]-1)
q:(m-[m/2],p[m/2],k[m/2]+1,p[m/2]+1,....,km,pm)
  关键码k[m/2]与指向新结点q的指针形成一个二元组插入到这两个结点p,q的父节点中去。如果父节点也满了则就再分裂,一直到根节点。如果分裂了根,那么我们就创建一个新根,将分裂的这两个根作为新创建的根的孩子,这也是B树增加高度唯一的方法。虽然分裂结点是比较费时的,但是分裂一次我们可以插入多次。
处理孩子溢出还有其他方法,一种方法就是将孩子结点让给具有空间的兄弟收养,但是这样的话会影响到键,所这种方法需要修改父亲,但是它会倾向于让叶子结点更加饱满,会更加节省空间。

B树的删除:
  删除的过程与插入的过程相反,如果某叶子丢了孩子,他可能需要和另一片叶子进行合并,我们必须一直沿着树向上合并下去(一直向上合并出现的几率很小),但是再最坏的情况下,根结点丢失了一孩子,然后我们就要删除根,并使用另一个孩子作为根,这也是B树降低高度的唯一方法。
  如果想要删除一个关键码我们首先要找到这个关键码,如果B树中没有这个关键码,那么就删除失败。
  如果找到了这个关键码,但是这个关键码不再叶子结点中,则应该采用交换删除的思想,应该以结点P所指向的子树中的最小的关键码X来代替要删除的关键码,问题就又转换成了删除X了,直到X出现在叶子中间,我们才真正的删除X。在叶子结点之中删除关键码有以下四种情况。

  1、要删除的关键码所在的叶子结点就是根节点,那么直接删除之后再修改根节点中放入数据项即可。

  2、要被删除的关键码所在的叶节点不是根节点,且被删除前该叶节点中关键码的个数大于最低限度,即大于M/2-1。则直接删除即可。

  3、要被删除的关键码所在的叶节点不是根节点,且被删除前该叶子结点中关键码的个数已经等于最小限度M/2-1,但是这个叶子结点的左兄弟或者右兄弟的关键码个数大于最低限M/2-1。
这时候就可以向他的兄弟收养一个孩子,以达到新的平衡。
收养的方法如下(以收养右兄弟的孩子为例):
   3.1、将父亲结点中刚刚大于被删除关键码的关键码K下移到被删除的位置。
   3.2、将右兄弟中最小的关键码上移到父节点中k的位置
   3.3、将右兄弟中的最左子树的指针平移到被删除关键码所在结点中的最后位置
   3.4、在右兄弟的结点中再将被移走的关键码和指针位置用剩余的关键码和指针填补,调整。

  4、被删除的关键码所在的叶节点删除前的关键码个数已经达到最低限度M/2-1,并且它的右兄弟(或左兄弟)也是最低限度M/2-1,则这时候就要将这两个结点合并。
合并方法如下:
  4.1、将父结点p中相应的关键码下移到选定保留的结点中,若要合并p子树指针p1和p2所指向的结点,且要保留p1所指结点,则把p中关键码K2下移到p1所指的结点之中。
  4.2、把p中子树p2所指结点中的全部指针和关键码都搬到p1所指结点的后面,删除p2所指结点。
  4.3、在父节点p中用后面剩余的关键码和指针填补关键码K2和指针p2。
  4.4、在修改父节点p和选定保留的结点
在合并的过程中,父节点的关键码个数减少了,所以还要向上继续判断满不满足平衡,如果父节点不满足,则一直重复上面的步骤。最坏的情况下,这种自下而上的处理要到根节点。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值