二叉搜索树、B树以及B+树

二叉搜索树(BST):

根节点的值大于其左子树中任意一个节点的值,小于其右节点中任意一节点的值,这一规则适用于二叉查找树中的每一个节点。其搜索效率与二叉树的树高有关,其查询时间复杂度为O(logN).

搜索节点:查找某个数字X,从根节点开始比较。如果X比根节点大,则去与根节点的右节点比较,如此类推,直到找到X(或子节点为空)为止。

插入新节点:如果新节点的key在树中已经存在,则把旧节点覆盖;如果没有,则插入。

查找最小值、最大值:最小值始终在左下的叶子节点、最大值始终在右下的叶子节点。

删除节点:A. 这个节点没子节点,此情况最为简单,直接删除这个节点即可。

         B. 这个节点只有一个子节点,把这个子节点和这个节点的父节点相连,然后删除这个节点

         C. 这个节点有两个子节点:

            1. 从此节点的右节点下面找出最小的节点X。

            2. 因为X节点是最小的,所以它的子节点数量肯定小于等于1个,把此子节点连到X的父节点上。

            3. 然后用X节点替换要删除的节点。

            4. 删除要删除的节点。

优点:查找速度、比较效率较高。

缺点:磁盘io较多,最坏的情况是io数等于树高。

所以,就想办法将“瘦高”的BST变得“矮胖”。

B-树( Balance-Tree)

B-树(不读做B减树)是一种多路平衡树,每个节点可以包含多个孩子,其上限k取决于磁盘大小,我们也把k称为树的阶。

一个m阶的B树具有如下几个特征:

1.根结点至少有两个子女。

2.每个中间节点都包含k-1个元素和k个孩子,其中 m/2 <= k <= m

3.每一个叶子节点都包含k-1个元素,其中 m/2 <= k <= m

4.所有的叶子结点都位于同一层。

5.每个节点中的元素从小到大排列,节点当中k-1个元素正好是k个孩子包含的元素的值域分划


3阶B-树

拿(2,6)结点为例:包含两个元素(2与6),以及3个孩子1,(3,5),8,并且1小于2,(3,5)介于2与6之间,8大于2,符合特征。

相较于二叉搜索树,查询过程的比较次数并不比二叉搜索树少,尤其单个结点中的元素量较多时,但相较于磁盘io,内存中的比较耗时基本可以忽略,故而,只要树的高度足够低就可以降低IO次数,大大提升查找性能。

插入操作:

       1、 若该结点中关键码个数小于m-1,则直接插入即可。

  2、 若该结点中关键码个数等于m-1,则将引起结点的分裂。以中间关键码为界将结点一分为二,产生一个新结点,并把中间关键码插入到父结点(k-1层)中

  重复上述工作,最坏情况一直分裂到根结点,建立一个新的根结点,整个B树增加一层。


删除操作:

根据key删除记录,如果B树中的记录中不存对应key的记录,则删除失败。

1)如果当前需要删除的key位于非叶子结点上,则用后继key(这里的后继key均指后继记录的意思)覆盖要删除的key,然后在后继key所在的子支中删除该后继key。此时后继key一定位于叶子结点上,这个过程和二叉搜索树删除结点的方式类似。删除这个记录后执行第2步

2)该结点key个数大于等于Math.ceil(m/2)-1,结束删除操作,否则执行第3步。

3)如果兄弟结点key个数大于Math.ceil(m/2)-1,则父结点中的key下移到该结点,兄弟结点中的一个key上移,删除操作结束。

否则,将父结点中的key下移与当前结点及它的兄弟结点中的key合并,形成一个新的结点。原父结点中的key的两个孩子指针就变成了一个孩子指针,指向这个新结点。然后当前结点的指针指向父结点,重复上第2步。

原始状态:

删除27


原始状态:

删除32,父节点下移与兄弟节点结合。

[参考博客]https://www.cnblogs.com/nullzx/p/8729425.html

应用场景:文件系统、部分数据库索引(非关系型数据库MongoDB);

B+树

B+树是B-树的变体,具有更高的查询性能,MySql数据库的索引就是使用的B+树进行查询。

m阶的B+树具有如下几个特征:

1.有k个子树的中间节点包含有k个元素(B树中是k-1个元素),每个元素不保存数据,只用来索引,所有数据都保存在叶子节点

2.所有的叶子结点中包含了全部元素的信息,及指向含这些元素记录的指针,且叶子结点本身依关键字的大小自小而大顺序链接

3.所有的中间节点元素都同时存在于子节点,在子节点元素中是最大(或最小)元素。最大/小的元素始终在根节点。

特点描述:

每个父节点元素都出现在子节点中,并且是最大/小的元素。

每个叶子节点都带有指向下一个叶子节点的指针,形成了一个有序链表。

仅叶子节点有卫星数据,其它中间节点都是索引,在非聚集索引(NonClustered Index)中,叶子节点带有指向卫星数据的指针。

由于B+树的中间节点不包含卫星数据,所以相较于B-树同一磁盘页可以容纳更多的节点元素。所以查询过程中的磁盘IO进一步降低。查询的终点始终在叶子节点所以使得查询效率非常稳定。

优势(相对于B-树):

1.单一节点存储更多的元素,使得查询的IO次数更少。

2.所有查询都要查找到叶子节点,查询性能稳定。

3.所有叶子节点形成有序链表,便于范围查询。

其插入删除操作与B树类似。

你可能感兴趣的:(二叉搜索树、B树以及B+树)