美文网首页
数据结构 - AVL树(艾薇儿树)

数据结构 - AVL树(艾薇儿树)

作者: 翀鹰精灵 | 来源:发表于2019-12-14 11:37 被阅读0次

    接上章:二叉搜索树(Binary Search Tree).

    通过二叉搜索树的学习,我们发现,二叉搜索树节点的添加和删除都是随机的,这里就会产生一种特殊情况,如下图所示:

    001.jpg

    此种情况,是从小到达的添加各个节点,此时二叉搜索树已经退化为链表了。或者删除节点,也可能会导致搜查搜索树退化成链表。那么,如何防止二叉搜索树退化成链表呢?
    因为二叉搜索树的复杂度在O(logn),所以在添加、删除二叉搜索树节点的时候复杂度一直维持在O(logn)即可。这里有一个平衡二叉搜索树的概念。

    平衡:当节点数量固定时,左右子树的高度越接近,这棵二叉树就越平衡(高度越低)。

    002.jpg

    西方有一句民谣是这样说的:“丢失一个钉子,坏了一只蹄铁;坏了一只蹄铁,折了一匹战马;折了一匹战马,上了一位骑士;上了一位骑士,输了一场战斗;输了一场战斗,亡了一个帝国。”所以,所谓平衡二叉树,其实就是在二叉树添加删除的过程中保证它的平衡性,一旦发自按有不平衡的情况,马上处理恢复平衡,这样就不会造成不可收拾的情况出现了。
    也就是说,在添加、删除操作之后,想办法让二叉搜索树恢复平衡(减小输的高度)即可。
    经典常见的平衡二叉搜索树也就是我们今天所说的AVL树。

    一、【AVL树】性质:

    ◼ 平衡因子(Balance Factor):某结点的左右子树的高度差
    ◼ AVL树的特点
    ◼ 每个节点的平衡因子只可能是 1、0、-1(绝对值 ≤ 1,如果超过 1,称之为“失衡”)
    ◼每个节点的左右子树高度差不超过 1
    ◼搜索、添加、删除的时间复杂度是 O(logn)
    添加、删除操作均会导致AVL树失衡

    例:我们先来看一个平衡二叉树构建的例子。假设我们有如下一个数组a[10]= {3,2,1,4,5,6,7,10,9,8},需要构建二叉搜索树。在没有学习AVL树之前,根据二叉搜索树的特性,我们通常会将它构建成如图003-图1所示。

    003.jpg

    虽然它完全符合二叉搜索树的性质,但是对于这样高度达到8的二叉搜索树来首,查找是非常不利的。我们更期望能够构建成如图003-图2所示的样子,高度为4的二叉搜索树才可以提高查找的效率。那么现在我们来看一下如何构建出如图003-图2所示的树结构。

    二、【AVL树】节点的增加和删除

    1.节点添加步骤:

    我们根据数组a[10]= {3,2,1,4,5,6,7,10,9,8},来一个个添加元素.

    1. 前两位【3】和【2】我们都很正常的构建,到了第三个数字节点【1】的时候,发现此时根节点【3】的平衡因子变成了2,此时整棵树都成了最小的不平衡子树,因此需要调整。所以需要将整个树进行右旋转(顺时针旋转),此时节点【2】成了根节点,【3】成为【2】的右孩子,这样三个节点的平衡因子值均为0,非常的平衡,完成了平衡二叉树的调整。如下图所示:

    004.jpg

    2. 接着添加节点【4】,平衡因子此时没发生改变,如图005所示

    005.jpg

    3. 接着添加节点【5】,节点【3】的平衡因子值为-2,说明要旋转了。所以我们对这棵最小平衡子树进行左旋(逆时针旋转),如图006所示,此时整个树又达到了平衡。

    006.jpg

    4. 继续添加节点【6】,发现根节点【2】的平衡因子变成了-2,如图007-图1所示。所以需要对根节点进行左旋转,注意此时本来根节点【3】是【4】的左孩子,由于旋转后需要满足二叉搜索树的性质,所以它成了节点【2】的右孩子。如图007-图3所示。

    007.jpg

    5. 继续添加节点【7】 ,发现节点【5】的平衡因子变成了-2,所以同样的左旋转,使得整棵树达到平衡,如图008所示。

    008.jpg

    6. 继续添加节点【10】,结构无变化,如图009所示。

    009.jpg

    7. 继续再添加节点【9】,此时节点【7】的平衡因子变成了-2,因为节点【9】是父节点【10】的左孩子,由于旋转后需要满足二叉搜索树的性质,所以这里需要进行两次旋转。
    7.1 先对节点【9】和节点【10】进行右旋转,使得节点10成了9的右子树。
    7.2 再以节点【7】为最小不平衡子树进行左旋转
    旋转过程如图010所示:

    010.jpg
    中间转换过程放大图如下:
    010-1.jpg

    8. 最后添加节点【8】,情况与刚刚类似,需要进行两次旋转。
    8.1 先以节点【9】为根节点,进行右旋
    8.2 再以节点【6】为根节点,进行左旋

    右旋转过程如图011所示:

    011.jpg

    右旋中间转换过程放大图:

    011-1.jpg
    左旋转过程如图012所示:
    012.jpg
    左旋中间转换过程放大图:
    012-4.jpg

    通过这个例子,我们可以总结出来,AVL树的旋转一共分为四种情况,分别是LL,RR,LR,RL。

    这里我们定义一个二叉搜索树P
    左子节点定义为L,
    右子节点定义为R,
    三角形代表子树,
    N定义为新增节点

    情况一:LL-右旋转(单旋)
    ◼ ① L.right = P.left;
    ◼ ② P = L.right
    ◼ ③ 让L成为这棵树的根节点
    ◼ ④ 整棵树达到了平衡
    注意:(1).LR、L、P的parent;(2).先后更新P、L的高度。

    LL.jpg

    情况二:RR-左旋转(单旋)
    ◼ ① R.left = P.right;
    ◼ ② P = R.left
    ◼ ③ 让R成为这棵树的根节点
    ◼ ④ 整棵树达到了平衡
    注意:(1).RL、R、P的parent;(2).先后更新P、L的高度。

    RR.jpg

    情况三:LR-左右旋转(双旋)
    ◼ 只需要先旋转,使平衡因子BF值符号统一,然后再进行旋转。

    LR.jpg

    情况四:RL-右左旋转(双旋)
    ◼ 只需要先旋转,使平衡因子BF值符号统一,然后再进行旋转。

    RL.jpg
    2.节点删除步骤:

    添加节点可能导致AVL树失衡,那么节点也可能导致AVL树失衡。如下图所示,删除节点后平衡因子如下:

    删除节点.JPG

    ◼ 删除子树中的 16
    ◼ 可能导致了父节点15失衡了。这里属于LL的情况,所以进行左旋转,调整后如下所示:

    旋转.png

    好了,AVL树的学习先暂且到这里,后序如果有更深入的了解,继续补充学习。

    相关文章

      网友评论

          本文标题:数据结构 - AVL树(艾薇儿树)

          本文链接:https://www.haomeiwen.com/subject/ijrmgctx.html