文章目录
1、AVL树(平衡二叉树BBST):
AVL树本质上是一颗二叉查找树,但是它又具有以下特点:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。在AVL树中任何节点的两个子树的高度最大差别为一,所以它也被称为 平衡二叉树
。下面是平衡二叉树和非平衡二叉树对比的例图:
平衡因子(bf)
:结点的左子树的深度减去右子树的深度,那么显然-1<=bf<=1;
AVL = 适度平衡:对于高度为h的AVL树,至少包含S(h) = fib(h+3) -1 个节点。即有 S(h) = 1 + S(h-1) + S(h-2)
2、AVL树的作用
对于一般的二叉搜索树,其期望高度(即为一棵平衡树时)为log2N,其各操作的时间复杂度(O(log2n))同时也由此而决定。但是,在某些极端的情况下(如在插入的序列是有序的时),二叉搜索树将退化成近似链或链,此时,其操作的时间复杂度将退化成线性的,即O(n)。我们可以通过随机化建立二叉搜索树来尽量的避免这种情况,但是在进行了多次的操作之后,由于在删除时,我们总是选择将待删除节点的后继代替它本身,这样就会造成总是右边的节点数目减少,以至于树向左偏沉。这同时也会造成树的平衡 性受到破坏,提高它的操作的时间复杂度。
例如:我们按顺序将一组数据1.2.3.5.10.20分别插入到一颗空二叉查找树和AVL树中,插入的结果如下图:
由上图可知,同样的结点,由于插入方式不同导致树的高度也有所不同。特别是在带插入结点个数很多且正序的情况下,会导致二叉树的高度是O(N),而AVL树就不会出现这种情况,树的高度始终是O(lgN).高度越小,对树的一些基本操作的时间复杂度就会越小。这也就是我们引入AVL树的原因
3、AVL树的基本操作
AVL树的操作基本和二叉查找树一样,这里我们关注的是两个变化很大的操作:插入和删除!
在AVL树中刚插入一个节点后失衡节点个数最多为O(lgn)
在AVL树中刚删除一个节点后失衡节点个数最多为O(1)
我们知道,AVL树不仅是一颗二叉查找树,它还有其他的性质。如果我们按照一般的二叉查找树的插入方式可能会破坏AVL树的平衡性。同理,在删除的时候也有可能会破坏树的平衡性,所以我们要做一些特殊的处理,包括:单旋转和双旋转!
对于必须重新平衡的节点a,不平衡主要出现在以下4种情况中:
- 对a的左儿子的左子树进行一次插入 (1和4镜像对称)
- 对a的左儿子的右子树进行一次插入 (2和3镜像对称)
- 对a的右儿子的左子树进行一次插入
- 对a的右儿子的右子树进行一次插入
对插入操作的平衡有两种方法:单旋、双旋
AVL树的插入,双旋转的第一种情况—左右(先左后右)旋:
由上图可知,我们在T结点的左结点的右子树上插入一个元素时,会使得根为T的树的左右子树高度差的绝对值不再 < 1,如果只是进行简单的右旋,得到的树仍然是不平衡的。我们应该按照如下图所示进行二次旋转:
左右情况的左右旋转实例:
AVL树的插入,双旋转的第二种情况—右左(先右后左)旋:
由上图可知,我们在T结点的右结点的左子树上插入一个元素时,会使得根为T的树的左右子树高度差的绝对值不再 < 1,如果只是进行简单的左旋,得到的树仍然是不平衡的。我们应该按照如下图所示进行二次旋转:
右左情况的右左旋转实例:
4、AVL树评价
优点:无论查找、插入或者删除,最坏情况下的复杂度均为O(logn),O(n)的存储空间
缺点:
借助高度或者平衡因子,需要改造元素结构,或额外封装
实测复杂度与理论值尚有