码迷,mamicode.com
首页 > 其他好文 > 详细

5、B数、B+数、红黑树

时间:2019-09-30 12:26:33      阅读:85      评论:0      收藏:0      [点我收藏+]

标签:防止   现在   平衡   指针   watch   例子   方式   线段   nal   

2-3树

技术图片

关键字 1-2 个
子节点 2-3 个

平衡树:子节点的高度一致

B树(Balacned Tree)

一种平衡的多分树

平衡:所有的叶结点在同一层,所以每个子节点的高度一致

m阶B树的结构定义

1、每个结点至多有m个子结点
2、除根节点和叶节点外,其他每个结点至少有m/2(向上取整)个结点
3、根结点至少有两个子结点

  • 唯一例外的是根节点就是叶结点时没有子结点
  • 此时B树只包含一个结点

4、所有的叶结点在同一层(平衡)
5、有k个子节点的非根节点恰好包含k-1个关键码

B树的性质

1、树高平衡,所有叶结点都在同一层
2、关键码没有重复,父结点中的关键码是其子结点的分界
3、B树把(值接近)相关记录放在同一个磁盘页中,从而利用局部性原理
4、B树保证树中至少有一定比例的结点是满的(每个结点有至少有m/2个子节点,半满)

  • 这样能改进空间的利用率(如果每个节点只有1个子节点,BST,树高会很高,空间利用率低)
  • 减少索引和更新操作的磁盘读取数目(如果每个节点有m个子节点,全满,那么每次插入的时候没处插了)
QM总结:
  • 除根节点和叶节点外,M阶B树每个节点有m/2~m个结点,根节点至少有两个子节点(插入时多次分裂)
  • 有k个子节点的非根节点恰好包含k-1个关键码
  • 父结点中的关键码是其子结点的分界

B树的节点结构

B树的一个包含j个关键码,j+1个指针的节点的一般形式为:

P0,K1,P1,K2,P2....Kj,Pj  #j个关键码,j+1个指针指向子节点

其中ki是关键码值,K1<K2<….<Kj
Pi是指向Ki到Ki+1之间的关键码的子树的指针

QM总结:
  • 如果有j个关键字,那么有可以表示j+1个区间,即有j+1个子节点
  • 关键词下标从1开始,P从0开始,Pi是指向Ki到Ki+1之间的关键码的子树的指针
  • 举个例子:P0指向K0到K1之间,即小于K1的,P1指向K1到K2

技术图片

B树结点抽象数据类型

class BNode{
    int n;//子节点的个数
    BNode<Key> *parent;//指向父节点的指针(可有可不有)
    Key key[MAXREC];//存储关键码的数组,最多有MAXREC个关键码
    BNode<Key> *ptr[MAXREC+1];//指向子节点的指针,最多有MAXREC+1个指针
}

B树的查找

1、把根节点读出来,在根节点所包含的关键码K1…Kj中查找给定的关键码值。当关键码不多时,就用顺序检索,当节点包含的关键码较多时,可以用二分检索。如果找到则检索成功

2、否则,确定要查的关键码指在某个Ki和Ki+1之间,那么去Pi所指向的节点继续查找

下图为查找24的过程

技术图片

如果树高为h,则查找时访问外存的次数是h

注意:
每个关键码表示索引,找到索引后,每个关键码还对应一个指向外存的指针,这样通过索引才可以访问到完整的记录

B树的插入(分裂向上生长)

情况1:

首先判断关键码14是否存在,按照图中的轨迹查找,此时到15所在的节点,遍历后发现没有14,则在该节点中插入

此时外存读的次数是3,写的次数是1

技术图片

情况2:

插入可能导致B树朝着根的方向生长,即当插入位置超过关键字的最大个数,节点需要进行分裂

如插入55,但2-3树要求关键字数只由1~2个,此时插入节点50,52已经达到个数,55无法直接插入,需要进行分裂

技术图片

50 52 55如何拆分?

父节点需要增加一个节点进行区分子节点拆分后的节点,采用二分的方法,将中间的52送到父节点,得到结果:

此时读的次数3,写的次数3(申请两个节点,并分别写入,这里包含两次写,还有在父节点中写入1次)

技术图片

情况3:

多次分裂,树向上生长

技术图片

最终的结果是:

技术图片

B数的删除(向左或向右合并)

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+树是B树的一种变形,是在叶结点上存储信息的树

  • 所有的管家那么均出现在叶结点上
  • 各层节点中的关键码均是下一层相应节点中最大关键码(或最小关键码)的复写

B+树的结构定义

  • 每个节点至多有m个子节点
  • 每个结点(除根外)至少有m/2(向上取整)个子结点
  • 根节点至少有两个子结点
  • 有k个子结点的必有k个关键码(这个是与B树的差别)
QM总结:
  • 根节点有2~m个子节点
  • 除根节点外有m/2(向上取整)~m个子结点
  • 有k个子结点的节点有k个关键字(这是与B树的结构差别,B树有k-1个关键字)

技术图片

  • m阶B+树有m个子节点,也有m个关键字
  • m个关键字是子结点的复写,当前层的关键码是其每个子结点关键码的最大关键码(也可以是最小)
  • 根节点是线性索引,可以顺序查找;再加上多分树形查找
  • 树形索引中不包含指向真实数据位置的指针,必须索引到树的叶子节点才算找到;好处是可以提高树的阶数,降低树的高度,加速索引速度

B+树的插入

如下3阶B+树,节点最多有3个关键码,当插入15后,查询到10 23这个节点,插入15。父节点不需要重写

技术图片

3阶B+树插入16后,叶子节点的关键为16超过最大阶3,所以需要分类成10、15和16、23,并增加分类节点之间的线性链接,修改父节点的关键码,每个关键码是子结点关键码最大值的复写

技术图片

多次分裂

技术图片

B+树的删除

如下B+树删除23,首先需要查找23;第一个节点判断,23<=35,到第二个子结点查找;23<=23,在第一个子结点中查找;删除关键码23;

此时父节点中的23能够正确标识父节点的区间,所以不进行更新(类似线段树中的延迟更新)

技术图片

B树与B+树的区别

节点结构:

  • 当前节点有k个子结点,B树有k-1个关键码,B+树有k个关键码
  • B树当前节点的关键码类似BST是子结点关键码的分割,B+树当前节点的关键码是子结点的复写(子结点关键码的最大值或最小值)

查找:

B树每个节点保存了指向真实位置的指针,找到关键码就能找到真实位置;B+树必须索引到叶子节点;B+树提供了索性查找和顺序查找两种方式

实际中使用B+树特别多

参考

第10章 索引——2(B树,B树) 标清
https://www.youtube.com/watch?v=vBD6Ve8VryY

原文:大专栏  5、B数、B+数、红黑树


5、B数、B+数、红黑树

标签:防止   现在   平衡   指针   watch   例子   方式   线段   nal   

原文地址:https://www.cnblogs.com/petewell/p/11611846.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!