Java数据结构之 AVL树(平衡二叉树)简析

AVL(即平衡二叉树)树是带有平衡条件的二叉查找树(二叉查找树即左孩子小于根节点,右孩子大于根节点的二叉树)。一颗AVL树是其每个节点的左子树和右子树的高度最多差 1 的二叉查找树(空树的高度定为-1),只有一个节点的树高度为0。在高度为h的AVL树中,最少节点数S(h)=S(h-1)+S(h-2)+1,对于h=0,S(h)=1;h=1,S(h)=2。

当进行插入操作时,我们需要更新通向根节点路径上那些节点的所有平衡信息,而插入操作隐含着困难的原因在于,插入一个节点可能破坏AVL书的特性。如果发生这种情况,那么就要考虑这一步插入完成之前恢复平衡的性质,这步操作称为旋转

我们把必须重新平衡的节点叫做 α ,由于任意节点最多有两个儿子,因此出现高度不平衡就需要 α 点的两课子树的高度差2,这种不平衡可能出现在下面四种情况中:

1. 对 α 的左儿子的左子树进行一次插入。

2. 对 α 的左儿子的右子树进行一次插入。

3.对 α 的右儿子的左子树进行一次插入。

4.对 α 的右儿子的右子树进行一次 插入。

恢复有两种旋转:

单旋转:对于1、4情况使用单旋转。

《Java数据结构之 AVL树(平衡二叉树)简析》

旋转前:节点k2不满足AVL平衡性质,因为它的左子树比右子树深2层。该图所描述的情况只是情形1的一种可能的情况,在插入之前k2满足AVL性质,但在插入后性质被破坏了。子树X已经多出一层,这使得它比子树Z深 2 层。Y不可能和新X在同一水平上,因为那样的话k2在插入之前就已经失去平衡了;为了使树恢复平衡,我们把X上移一层,把Z下移一层,移动后如下图所示。

《Java数据结构之 AVL树(平衡二叉树)简析》

                           旋转后

 

下面这种情况:假设从初始的空AVL树开始插入关键字3、2和1,然后依序插入4~7。在插入关键字1时第一个问题出现了,AVL性质在根处被破坏。我们在根与其左儿子之间施行单旋转修正这个问题。总结:AVL性质在哪个节点被破坏,就在哪个节点进行修复(修复后一定要让树的其余部分被告知该变化,若节点3有父节点,一定要让父节点指向节点3的引用重新指向2)。

《Java数据结构之 AVL树(平衡二叉树)简析》

双旋转:对于2、3情况使用双旋转。

若子树Y太深,单旋转没有减低它的深度,解决这个问题的双旋转在下图给出。

《Java数据结构之 AVL树(平衡二叉树)简析》

恰好树B或树C中有一棵比D深两层,但是我们不能肯定是哪一棵(事实上这并不要紧)。为了重新平衡,我们不能再把k3作为根节点了,唯一的选择就是把k2作为新的根。这迫使k1是k2的左儿子,k3是k2的右儿子,从而完全确定了这四棵树(A、B、C、D)的最终位置。容易看出,最终得到的树符合AVL树的性质。(对称情形恢复方法也是同理)

    原文作者:AVL树
    原文地址: https://blog.csdn.net/qq_34999633/article/details/82903191
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞