zoukankan      html  css  js  c++  java
  • [zz]AVL树

    转载自:http://www.cnblogs.com/xiao-cheng/archive/2011/10/04/2198972.html

    定义:一棵空二叉树是AVL树,如果T是非空二叉树,TL和TR分别是其左子树和右子树,

    则当且仅当TL和TR都为AVL树且|HL-HR|<=1时,T是AVL树。

    由定义知道一个AVL树的任何节点的左右子树的高度之差不超过1,这是AVL树最基本的特征。

    AVL树的高度:(固定节点数计算最大高度)

    记N_h为一棵高度为h的AVL树具有的最小节点数,则最坏情况是它的左右子树的高度不等,

    一个是N_(h-1)和N_(h-2),从而得到

    N_h=N_(h-1)+N_(h-2)+1            N_0=0,N_1=1

    这类似于Fibonacci数列:F_n=F_(n-1)+F_(n-2),(F_0=0,F_1=1)

    而F_h=(1+sqrt(5))^h/sqrt(5)

    从而高度h和节点数是对数关系,因此 h=O(log(N_h))

    由此容易知道在不考虑恢复AVL树的前提下,它的插入,删除和查找的工作量不超过O(n)。

    AVL树节点的平衡因子

    AVL树节点的平衡因子定义为其左子树的高度减去右子树的高度,我们可以在插入和删除操作的时候更新平衡因子。

    一棵AVL树的各节点平衡因子为1,-1, 0

    树的旋转

    在介绍插入和删除操作之前首先介绍树的旋转操作

    树的旋转操作是为了改变树的结构,使其达到平衡。旋转总共分为左旋和右旋两类

    左旋

    如图为树的以B为轴左旋示意图,从右到左是以A为轴右旋,树的旋转操作要特别注意儿子节点是否为空

    顶层节点是否为根节点。

    AVL树的插入操作

    插入操作只会改变被插入节点到根节点路径上的节点的平衡因子。

    因为在插入之前树是AVL树,因此各个节点的平衡因子是1,-1或0

    一、如果路径上节点平衡因子是0,则插入后不会打破这个节点的平衡性。

    二、如果路径上的节点的平衡因子是1或-1,则可能会打破平衡性,在这种情况下如果此节点的新的平衡

    因子是0,则刚好将其补的更加平衡,平衡性未打破;否则平衡因子变成2或-2,则需要进行调整。

    三、我们在对树进行调整后恢复子树相对于插入前的高度,不改变子子树的平衡因子。

    由以上三点:只需向根部查找从插入点开始第一个平衡因子不为0的节点,令该节点为A

    更新步骤:

    (1). 若A不存在,说明插入节点不影响平衡性,则自下而上更新平衡因子直到根部即可。

    (2). 若bf(A)=1且插入节点在A地右子树中,或者bf(A)=-1且插入节点在A的左子树中,则自下而上更新

    平衡因子直到A。(注:A的平衡因子变为0)

    (3). 若A的平衡性被打破,首先依然自下而上更新平衡因子,在按照下面进行分类:LL, LR, RR, RL

    原bf(A)=1, 新的bf(A)=2, LL, LR,

    原bf(A)=-1, 新的bf(A)=-2, RR, RL

    如图为RR的情况,LL情况类似,旋转后只需再次改变两个节点的平衡因子

    RR

    如下图为RL的情况,LR类似,旋转后需要再次改变三个节点的平衡因子

    RL

    至此,插入操作已经完成,可见最多多做两次旋转操作调整树的结构使之平衡。

    AVL树的删除操作:

    删除操作和插入操作一样,也是先直接删除二叉树节点,然后在更新平衡因子,

    调整AVL树使之平衡。

    这里所指的删除的节点是实际被删除的节点,删除操作不影响其子树的平衡因子。

    首先删除节点,然后沿着该节点的父节点向根部更新平衡因子,考虑更新后的节点A

    新的平衡因子,分为下面三种情况:

    (1)、如果bf(A)=0,则高度减少了1,从而继续向上找非平衡点。

    (2)、如果bf(A)=1或者-1,则之前必为0,从而不影响平衡性,结束。

    (3)、如果bf(A)=2(原来为1)或者-2(原来为-1),则A点非平衡。调整。

    以bf(A)=-2为例,称A为L不平衡

    如果A的右节点的平衡因子是0,则进行一次左旋转,如图:

    L0

    由于子树的高度和删除前一样,因此树已经平衡。

    如果A的右节点的平衡因子是-1,则称为L-1不平衡,也要进行一次做旋转。

    L-1

    树的高度减少1,这使得上面的祖先节点可能不平衡,一次还要沿着路径在向上

    寻找新的不平衡点,再次更新平衡因子,调整等。

    如果A的右节点的平衡因子是1,则称为L1不平衡,要进行两次旋转。

    L1

    此时要根据BL的情况决定A和B的新的平衡因子。

    由于树的高度减少了1,因此还要沿着路径继续向上寻找新的不平衡点。

    至此树节点的删除操作完成。

    总结

    归纳起来,AVL树的查找操作等同于一般二叉树,插入和删除操作除了一般的二叉树插入和删除

    还要更新树的平衡因子,当平衡因子被打破时要通过旋转恢复。而且在调整平衡时尽量影响局部范围。

  • 相关阅读:
    LeetCode Binary Tree Inorder Traversal
    LeetCode Populating Next Right Pointers in Each Node
    LeetCode Construct Binary Tree from Inorder and Postorder Traversal
    LeetCode Reverse Linked List II
    LeetCode Populating Next Right Pointers in Each Node II
    LeetCode Pascal's Triangle
    Palindrome Construct Binary Tree from Preorder and Inorder Traversal
    Pascal's Triangle II
    LeetCode Word Ladder
    LeetCode Binary Tree Zigzag Level Order Traversal
  • 原文地址:https://www.cnblogs.com/zhangzhang/p/2849462.html
Copyright © 2011-2022 走看看