c++

简介: avl

一、AVL树的定义
AVL树,全称 平衡二叉搜索(排序)树。

二叉搜索树虽可以缩短查找的效率,但如果数据有序或接近有序二叉搜索树将退化为单支树,查找元素相当于在顺序表中搜索元素,效率低下。因此,两位俄罗斯的数学家G.M.Adelson-Velskii和E.M.Landis在1962年发明了一种解决上述问题的方法:当向二叉搜索树中插入新结点后,如果能保证每个结点的左右子树高度之差的绝对值不超过1(需要对树中的结点进行调整),即可降低树的高度,从而减少平均搜索长度。

平衡因子(Balance Factor,简写为bf)
平衡因子(bf):结点的左子树的深度减去右子树的深度。也可以是右子树的深度减去左子树的深度。看个人实现而异。

即: 结点的平衡因子 = 左子树的高度 - 右子树的高度。
或者 节点的平衡因子 = 右子树的高度 - 左子树的高度。

AVL树本质上是一颗二叉查找树,但是它又具有以下特点:

它的左右子树都是AVL树
左右子树高度之差(简称平衡因子)的绝对值不超过1(-1/0/1)
这就是一颗AVL树

二、AVL树的作用
有一颗二叉树,他有n个节点,如果他是一颗二叉搜索树,他形状多样,可能会形成单枝树,高度为n,那么在这颗搜索树中查找元素的最坏时间复杂度为O(n),最好时间复杂度是O(l o g 2 n log_2 nlog
2

n)。
如果他是一颗AVL树,他的高度稳定为l o g 2 n log_2 nlog
2

n,查找元素的时间复杂度为O(l o g 2 n log_2 nlog
2

n)。
由上图可知,同样的结点,由于插入方式不同导致树的高度也有所不同。特别是在带插入结点个数很多且正序的情况下,会导致二叉树的高度是O(N),而AVL树就不会出现这种情况,树的高度始终是O(lgN).高度越小,对树的一些基本操作的时间复杂度就会越小。这也就是我们引入AVL树的原因。

三、AVL树的插入操作
插入——平衡因子的更新
在插入一个元素的时候,必然会引起平衡因子的变化,所以我们需要在插入的时候把平衡因子同时更新,在平衡因子大于1或者小于-1时,我们则需要进行旋转操作,进行调整,使平衡因子再次正常,从而保证这颗二叉树一直是一颗AVL树。

使用平衡因子计算: 右子树高度 - 左子树高度

情况一:

在插入元素后,需要更新父节点的平衡因子,在父节点的左子树插入元素,父节点的平衡因子-1,在父节点的左子树插入元素,父节点的平衡因子+1,如果父节点的平衡因子更新过后变为1或者-1,则需继续往上更新至根节点,因为1或者-1表示该节点的高度发生改变,需往上更新。

情况2:

在插入元素后,需要更新父节点的平衡因子,在父节点的左子树插入元素,父节点的平衡因子-1,在父节点的左子树插入元素,父节点的平衡因子+1,如果父节点的平衡因子更新过后变为0,则不需要继续向上更新,因为变为0只能说明该树高度没有变化,只是相对于原来变得平衡。

如果在更新平衡因子后,平衡因子不在(-1/0/1)范围时,则需旋转操作,下面讲解如何进行旋转操作

由于插入需要旋转的情况较多,大致可以分为四大类

插入——左单旋
动图演示

情况一
右子树高时,在右子树的右侧插入元素,此时需要左单旋

插入——右单旋
动图演示

情况二、
左子树较高时,在左子树的左侧插入元素,此时需要右单旋

插入——左右双旋
情况三、左子树较高时,在左子树的右侧插入元素,此时需要左右双旋,即:先对30进行左单旋,然后再对90进行右单旋

插入——右左双旋
情况四、右子树较高时,在右子树的左侧插入元素,此时需要右左双旋,即:先对90进行右单旋,然后再对30进行左单旋

相关文章
|
8月前
|
存储 Go C++
c++
this 全局函数
42 0
|
8月前
|
存储 人工智能 移动开发
数据结构
线性表
121 0
|
8月前
|
存储 安全 编译器
c++
c++基础性内容
57 0
|
8月前
|
机器学习/深度学习 算法
|
8月前
|
C++
c++
语块中的变量
24 0
|
8月前
|
存储 缓存 编译器
c++
类与对象
63 0
|
8月前
|
C++
c++
static in
40 0
|
2天前
|
SQL 容灾 关系型数据库
[版本更新] PolarDB-X V2.4 列存引擎开源正式发布
[版本更新] PolarDB-X V2.4 列存引擎开源正式发布!
[版本更新] PolarDB-X V2.4 列存引擎开源正式发布
|
2天前
|
运维 监控 Cloud Native
如何设计与构建 FinOps 流程、团队、体系与目标
企业 FinOps 实施不是一蹴而就的项目,如果您正在推进企业云原生 FinOps 落地,除了选择合适的技术手段,企业内部的流程和体系建设也尤为重要。
162146 7
|
2天前
|
分布式计算 Java API
Java8 Lambda实现源码解析
Java8的lambda应该大家都比较熟悉了,本文主要从源码层面探讨一下lambda的设计和实现。
162552 6