史上最详细关于树算法(二叉树,AVL树,平衡树,红黑树,伸展树,B树)

二叉树

二叉查找树的特点就是左子树的节点值比父亲节点小,而右子树的节点值比父亲节点大

正常:查找时间复杂度O(logn)

缺点:极端:O(n) 全在一列

在这里插入图片描述

AVL树

主要特点 :任何给定的节点的子树的高度相差最多为1

保证平衡性的最大的目的就是降低树的高度,因为树的查找性能取决于树的高度。所以树的高度越低搜索的效率越高!

平衡二叉树

平衡二叉树特点:
①非叶子节点最多拥有两个子节点。
②非叶子节点值大于左边子节点、小于右边子节点。
③树的左右两边的层级数相差不会大于1。
④没有值相等重复的节点。

目的:解决二叉树的出现极端情况而影响查找效率 使用方法:单旋转(当太高的树到给点节点路径为一条直线,或者说是外部的树),**双旋转(**当太高的树是内部,或者到给定节点路径不为直线,先旋转内部,在旋转外部)

旋转的方向根据路径连接(如/ 则顺时针旋转,\则逆时针旋转),

查找时间复杂度:O(logn)

缺点:由于特点,在插入删除频繁时,经常要进行旋转,影响效率_>红黑树

红黑树(只有叶子节点存储数据)

特点:

1.叶子节点都是黑色的. 根节点不一定要为黑色.

在这里插入图片描述

2.不能连续出现红色节点.(该节点为红色,子节点必须为黑色)

3.树的所有叶节点必须具有相同的黑色深度(叶节点到根节点的黑色节点个数减1)

2)为什么从每个叶子到根的所有路径上不能有两个连续的红色节点?

为了保证树的平衡,保证最长的路径最多是最短路径的的两倍。->保证时间复杂度在logn以内

想象一下,由于每条路径上的黑色节点都必须相等,所以最短的路径肯定是全是黑色节点。那最长的路径呢,如果要求红色的点不能连续,那最长的路径肯定是红黑相隔,由于根节点是黑色的,所以,最长的路径应该是黑色节点和红色节点一样多,也就是黑色节点的两倍。

红黑树的形成方法 :颜色翻转,单双旋转(根据红色节点到根节点是否为一条直线)

伸展树:

伸展树也是二叉树的变体.

特点:每次访问树时,通过旋转重排树,使得访问的节点位于树的根部.

B树:(B-,B+,B*),一般B树指的是B-树

B树是一种多叉树,平衡多路查找树.

需求(出现原因):

需求1(从内存占用角度):

在程序员算法书中是这样说的,{上述的树算法对于完全可以在内存中维护的数据工做得很好.如果不是这样,就需要一种适用于磁盘存储器的树算法.利用磁盘存储器具有它自己的一组特殊的限制:

  • 与访问内存中的数据所需的时间相比,访问磁盘上的数据非常慢.
  • 最好对相当大的数据块执行读/写操作.实际上一次读入的数据越多,就会做的越好(一定范围内).一般使用2048~4096字节的数据块大小.

简单翻译一下:当算法执行需要占用较大的空间(内存空间不够,内存空间价格高昂相比于磁盘空间),为了减少内存占用,就研发出了一种适用于磁盘存储器的树算法().

另一种需求说法:(从二叉树存在问题角度)

二叉树的操作效率较高,但是也存在问题.

二叉树需要加载到内存的,如果二叉树的结点少,没有什么问题,但是如果二叉树的结点很多(比如1亿), 就存在如下问题:

  • 问题1:在构建二叉树时,需要多次进行I/O操作(海量数据存在数据库或文件中),结点海量,构建二叉树时,速度有影响
  • 问题2:结点海量,也会造成二叉树的高度很大,会降低操作速度

第三种需求(从mysql/数据结构角度)

Mysql索引为什么用B+树而不用B-树 - 問天 - 博客园 (cnblogs.com)

先从数据结构的角度来看
  我们知道B-树和B+树最重要的一个区别就是B+树只有叶节点存放数据,其余节点用来索引,而B-树是每个索引节点都会有Data域。
  这就决定了B+树更适合用来存储外部数据,也就是所谓的磁盘数据。

从Mysql(Inoodb)的角度来看

B+树是用来充当索引的,一般来说索引非常大,尤其是关系性数据库这种数据量大的索引能达到亿级别,所以为了减少内存的占用,索引也会被存储在磁盘上。
那么Mysql如何衡量查询效率呢?磁盘IO次数,B-树(B类树)的特定就是每层节点数目非常多,层数很少,目的就是为了就少磁盘IO次数,当查询数据的时候,最好的情况就是很快找到目标索引,然后读取数据,使用B+树就能很好的完成这个目的,但是B-树的每个节点都有data域(指针),这无疑增大了节点大小,说白了增加了磁盘IO次数(磁盘IO一次读出的数据量大小是固定的,单个数据变大,每次读出的就少,IO次数增多,一次IO多耗时啊!),而B+树除了叶子节点其它节点并不存储数据,节点小,磁盘IO次数就少。这是优点之一。
  另一个优点是什么,B+树所有的Data域在叶子节点,一般来说都会进行一个优化,就是将所有的叶子节点用指针串起来。这样遍历叶子节点就能获得全部数据,这样就能进行区间访问啦。
(数据库索引采用B+树的主要原因是 B树在提高了磁盘IO性能的同时并没有解决元素遍历的效率低下的问题。正是为了解决这个问题,B+树应运而生。B+树只要遍历叶子节点就可以实现整棵树的遍历。而且在数据库中基于范围的查询是非常频繁的,而B树不支持这样的操作(或者说效率太低))

至于MongoDB为什么使用B-树而不是B+树,可以从它的设计角度来考虑,它并不是传统的关系性数据库,而是以Json格式作为存储的nosql,目的就是高性能,高可用,易扩展。首先它摆脱了关系模型,上面所述的优点2需求就没那么强烈了,其次Mysql由于使用B+树,数据都在叶节点上,每次查询都需要访问到叶节点,而MongoDB使用B-树,所有节点都有Data域,只要找到指定索引就可以进行访问,无疑单次查询平均快于Mysql(但侧面来看Mysql至少平均查询耗时差不多)。

总体来说,Mysql选用B+树和MongoDB选用B-树还是以自己的需求来选择的。

B树相对于红黑树的区别

在大规模数据存储的时候,红黑树往往出现由于树的深度过大而造成磁盘IO读写过于频繁,进而导致效率低下的情况。为什么会出现这样的情况,我们知道要获取磁盘上数据,必须先通过磁盘移动臂移动到数据所在的柱面,然后找到指定盘面,接着旋转盘面找到数据所在的磁道,最后对数据进行读写。磁盘IO代价主要花费在查找所需的柱面上,树的深度过大会造成磁盘IO频繁读写。根据磁盘查找存取的次数往往由树的高度所决定,所以,只要我们通过某种较好的树结构减少树的结构尽量减少树的高度,B树可以有多个子女,从几十到上千,可以降低树的高度。

补充:

减少磁盘IO访问次数(I/O访问时间通常为毫秒级,CPU活动一般发生在亚微妙级[比微妙大一些])

每次读写数据块大小(缓冲区)一般大小为2k~4K之间,原因在于大于4K后性能影响不大(在MS-DOS系统[微软磁盘操作系统]中),如下图:

IMG_20201112_204700

三种树的出现主要缘由:

B-树可以有效降低IO次数(通过降低树的高度,即每个节点可以存储多个数据,且每个节点根据n阶可以有个n-1个节点来降低树的高度),B+树将数据存放在叶子节点中又减少了内存的占用(想想只有到叶子节点时才比较大),B*树的改进是增大空间利用率,又进一步减少.

B-树:每个节点有会存储数据 B+树:只有叶子节点存储数据. ->B+树更适合用来存储外部数据(磁盘数据)

B+树最大空间浪费(1/2),B*(B+树的变体)最大浪费空间(1/3).

b树(b-树)

定义:

B树也称B-树,它是一颗多路平衡查找树。
我们描述一颗B树时需要指定它的阶数,阶数表示了一个结点最多有多少个孩子结点,一般用字母m表示阶数。当m取2时,就是我们常见的二叉搜索树。

m阶B树规则:

1.根节点可以只有一个元素,2个子节点
2.每个结点有k-1个元素,k个子节点(m/2<=k<=m)
3.叶节点有k-1个元素(m/2<=k<=m)
3.叶子节点都在同一层
4.元素大小按顺序排列(从左到右

在这里插入图片描述

详细增删例子:

https://blog.csdn.net/Fmuma/article/details/80287924
b树视频讲解:
https://www.bilibili.com/video/BV1et4y117wc?from=search&seid=2745291156776152836

B+树:

定义规则(基本相同与b树)

各种资料上B+树的定义各有不同,一种定义方式是关键字个数和孩子结点个数相同。这里我们采取维基百科上所定义的方式,即关键字个数比孩子结点个数小1,这种方式是和B树基本等价的。上图就是一颗阶数为4的B+树。

区别

B+树与B树最大的不同是内部结点(索引节点)不保存数据,只用于索引,所有数据(或者说记录)都保存在叶子结点中。
在这里插入图片描述

详细增删例子:

https://blog.csdn.net/Fmuma/article/details/80287924

B*树

规则:

B*树是B+树的变种,区别如下:
①首先是关键字个数限制问题,B+树初始化的关键字初始化个数是cei(m/2),B*树的初始化个数为cei(2/3m)。
②B+树节点满时就会分裂,而B*树节点满时会检查兄弟节点是否满(因为每个节点都有指向兄弟的指针),如果兄弟节点未满则向兄弟节点转移关键字,如果兄弟节点已满,则从当前节点和兄弟节点各拿出1/3的数据创建一个新的节点出来。

特点:

在B+树的基础上因其初始化的容量变大,使得节点空间使用率更高,而又存有兄弟节点的指针,可以向兄弟节点转移关键字的特性使得B*树额分解次数变得更少;

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值