AVL树基本原理

在算法与数据结构中对平衡二叉搜索树的AVL树的定义是如下,

a tree is balanced if and only if for every node the heights of its two subtrees differ by at most 1.

Trees satisfying this condition are often called AVL-trees( After their inventors). We shall simply call them balanced trees because this balance criterion appears a most suitable one.

the defination is not only simple. but it also leads to a manageable rebalancing procedure and an average search path length practically identical to that of TBE perfectly balanced tree. 

在平衡搜索树中,AVL-tree是最早提出来的。AVL-tree为了保证每次搜索的复杂度O(logn),规定每个节点的两个子树的高度差的绝对值最多为1. 这就是AVL-tree实现中引入的平衡因子,在具体实现中,就可以通过平衡因子来调整树,在失衡情况下,通过旋转来重新达到平衡。

那么在具体的实现中遇到这些难点:

1,BF(balance factor)

BF的调整,对于每个节点,如果每次调整树结构都去重新计算一遍两个子树的高度,那么效率就会大打折扣,绝对不可能通过这种方式实现。

2,树的旋转

在AVL-tree中,是通过旋转来重新达到树的平衡,那么旋转有那么方式。

3,节点的删除

删除叶节点相对简单,但涉及到包含子节点的节点,就相对比较复杂,应该怎么来处理。

树的旋转及BF调整

左旋

    a                      c
   /  \                    /  \
  b   c      =>      a     f
      /  \              /  \
     e   f           b   e

现在假设每个节点的高度为H(node),平衡因子为BF(node),左子树的高度减去右子树的高度。那么如图所示,

H(a)=1+max(H(b),H(c)); BF(a) = H(b)-H(c);

在一棵平衡的AVL-tree中,只有插入和删除操作,才能使树的平衡条件打破。现在主要以插入为主来具体描述下。在AVL-tree中的插入操作,首先就是用这个键值来在AVL树中查询,知道某个节点的叶节点为null,然后就把这个新节点安插在这个为null的叶节点的位置。如果找到,那就说明这个键值存在,插入失败。当安插好这个节点以后,它的父节点和祖先节点的平衡因子就可以变化,当首个祖先节点的平衡因子超出AVL-tree的定义范围(绝对值小于等于1)时,就需要通过旋转来调整这个子树,然后继续沿着父节点回溯到平衡因子满足条件为止,在最差的情况下,会回溯到根节点。

其实旋转根据平衡因子的值可以分为左旋和右旋,当BF<-1 时,只能做左旋,才能恢复平衡,如果右旋,只是加剧失衡而已。那么在调整后平衡因子肯定变化的是调整前失衡的节点(它恢复了平衡),可能变化为失衡节点的右子树(它有可能变得不平衡,需要再度旋转)。当BF>1 时,只能做右旋。同上。

在具体实现中,这个平衡因子就比较关键了,它决定了什么时候旋转,该怎么旋转。而BF在旋转前后的计算也是比较关键。那么分析一下BF在旋转前后都由哪些参数来决定,就能不通过遍历整个子树的高度来决定BF.

假如BF(a)<-1,旋转前的各个参数为h,bf,旋转后的各个参数为H,BF.那么旋转后受影响的平衡因子就是a和c。

bf(a)=h(b)-h(c); BF(a)=H(b)-H(e);

bf(c)=h(e)-h(f); BF(c)=H(a)-H(f);

因为在旋转前后平衡因子受影响的只有节点a,c。其他节点的平衡因子和节点高度是没有发生变化的。

所有h(b)==H(b), h(f)==H(f), h(e)==H(e);

那么在旋转前后a,c节点的BF变化为:

vary(a) = BF(a) – bf(a) = (H(b)-H(e)) – (h(b)-h(c)) = h(c) – h(e);

vary(c) = BF(c) – bf(c) = (H(a)-H(f)) – (h(e)-h(f)) = H(a) – H(e);

由以上可以得到一个基本的结论,在left rotation中,失衡节点(a)的BF调整只与旋转前c,e子树相关。右子节点c的平衡因子和旋转后的a,e子树相关。

如图所示,h(c)=1+max(h(e), h(f)), 当bf(c)<0时,h(c)=1+h(f), so vary(a) = 1+h(f) – h(e) = 1-(h(e) – h(f)) = 1 – bf(c); 

当bf(c)>=0时, h(c)=1+h(e), so vary(a) = 1 + h(e) – h(e) = 1;

H(a)=1 + max(H(b), H(e)), 当BF(a)<=0时, H(a)=1+H(e), so vary(c) = 1 + H(e) – H(e) = 1;

当BF(a)>0时,H(a)=1+H(b), so vary(c) = 1+ H(b) – H(e) = 1 + BF(a);

由以上推断可以得出,调整后的a平衡因子由调整前的c的平衡因子决定,调整后的哦c平衡因子由调整后的a平衡因子决定。

BF(a) = bf(a)+vary(a) = bf(a) + 1 – bf(c);

BF(c) = bf(c)+vary(c) = bf(c) + 1 + BF(a);

由以上推断的结果,对于左旋的伪代码就可以这么表述:

//失衡节点先调整

a->bf++;

if(c->bf<0)

a->bf -= c->bf;

//失衡节点右节点后调整

c->bf++;

if(a->bf>0)

c->bf += a->bf;

右旋

     a                   b
    /  \                 /   \
   b  c      =>    e    a
  /  \                      /   \
 e   f                    f    c

因为左旋和右旋是对称的,所有不用推算也能写出调整后平衡因子的伪代码。

a->bf–;

if(b->bf>0)

a->bf -= b->bf;

b->bf–;

if(a->bf<0)

b->bf += a->bf;

再把过程简单写一下

假如BF(a)>1, 那么如图平衡因子受影响的是节点是a,b。

bf(a)=h(b)-h(c); BF(a)=H(f)-H(c);

bf(b)=h(e)-h(f); BF(b)=H(e)-H(a);

因为在旋转前后,h(e)==H(e), h(f)==H(f), h(c)==H(c);

vary(a) = BF(a) – bf(a) = H(f)-H(c) – (h(b)-h(c)) = -(h(b)-h(f));

vary(b) = BF(b) – bf(b) = H(e)-H(a) – (h(e)-h(f)) = -(H(a)-H(f));

h(b)=1+max(h(e), h(f)), 当bf(b)<=0时,h(b)=1+h(f), vary(a)=-(1+h(f)-h(f))=-1;

当bf(b)>0时,h(b)=1+h(e), vary(a)=-(1+h(e)-h(f)) = -1-bf(b);

H(a)=1+max(H(f), H(c)), 当BF(a)<0时, H(a)=1+H(c), vary(b)=-(1+H(c)-H(f)) = -1+(H(f)-H(c)) = -1 + BF(a);

当BF(a)>=0时, H(a)=1+H(f), vary(b)=-(1+H(f)-H(f)) = -1;

BF(a) = bf(a)+vary(a) = bf(a) -1 – bf(b);

BF(b) = bf(b)+vary(b) = bf(b) -1 + BF(a);

avl树的旋转,当avl树平衡条件打破以后,我们是通过旋转来使avl树重新满足平衡条件。旋转由两个节点参与,也就是失衡节点以及它的一个子节点(由平衡因子来决定是左子节点(bf>0)或者右子节点(bf<0))。所以旋转分为左旋转和右旋转,而他们也是对称的。在插入节点的时候有的地方也会提到双旋转,其实也是由左右两种旋转构成的,双旋转的引入是为了解决单一的左右旋转引起的死循环问题。

关于死循环问题是这样引起的,也就是所谓的内侧插入,因为左右旋转是对称的,所以只拿左旋转来说,当失衡节点平衡因子是-2时,其右子节点bf为1,和失衡节点不同侧,左旋一次,根节点bf为2,左子节点bf为-1,这相当于变成了右旋传的内侧插入,因为左右旋转是对称的,所以插入节点必须和父节点同侧,否则就必须先做一次旋转调节,使他们同侧,才能避免这种死循环的情况出现。

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