AVL树

定义

每个结点的左子树和右子树的高度最多差1的二叉查找树(空树的高度定义为-1)。

最大高度

AVL树的最大高度为1.44log(N+2)-1.328,但是实际上的高度只略大于logN。在高度为h的AVL树中,最少结点数S(h)由S(h)=S(h-1)+S(h-2)+1给出。对于h=0,S(h)=1;h=1,S(h)=2。函数S(h)与斐波那契数密切相关,由此推出高度的界。

插入

在插入以后,只有那些从插入点到根结点的路径上的结点的平衡可能被改变,因为只有这些结点的子树可能发生变化。只需在第一个 这样的结点(即最深的结点)重新平衡这棵树,就能保证整棵树的平衡。

不平衡性分析

我们将必须平衡的结点成为a。由于任意结点最多有两个子结点,因此出现 高度不平衡时只需要a的两颗子树的高度差为 2。主要包含四种情况:
1、对a的左儿子的左子树进行一次插入
2、对a的左儿子的右子树进行一次插入
3、对a的右儿子的左子树进行一次插入
4、对a的右儿子的右子树进行一次插入

调整情形1的单旋转

0

分析

结点k2不满足 AVL平衡的性质,因为它的左子树比右子树深2层(图中间的几条虚线表示树的各层)。该图所描述的情况只是情形1的一种可能,在插入之前k2满足AVL性质,但在插入之后这种性质被破坏了。子树X已经生长出一层,这使得它比子树Z深出2层。Y不可能与新X在同一水平上,因为那样 k2在插入前就已经失去了平衡了,Y不可能与Z在同一层上,因为那样k1就会是在通向根的路径上破坏AVL平衡条件的第一个结点 。

调整操作

对根结点k2执行右旋转,使得k1子树高度+1,k2子树高度-1
X向上移动了一层,Y停在原来的水平上,而Z下移一层。不仅如此,整个树的新高度恰恰与插入前原树的高度相同,而插入操作却使得子树Z长高了。因此,通向根结点的路径的高度不需要进一步的修正,因而也不需要进一步的旋转。

调整情形2的双旋转

0

分析

如图k1的右子结点必然非空,可以将它假设为一个根和两颗子树。于是可以将整棵树看成是4棵子树由3个结点链接。如图所示恰好树B和树C中有一棵比D深2层,但是无法 确定哪一棵。可以将B、C子树的高度画成3/2层。

调整操作

为了调整树的高度可以先左旋转树的左子结点k1,再右旋转根结点k3。这样子树B、D的高度-1,子树D的高度+1。整棵树的高度恢复到新增前。

删除

删除操作的分析与插入操作类似,因为可能存在两个子树高度比被删除的子树高度高的场景。调整后树的高度比删除前树的高度变低。因此需要一直往上平衡到根结点。
 
 
public class AVLBST<Key extends Comparable<Key>, Value> {
    private static final int ALLOWED_IMBALANCE = 1;
    private Node root;
    
    public void put(Key key, Value val) {
        root = put(key, val, root);    
    }
    
    private Node put(Key key, Value val, Node x) {
        if(x == null) return new Node(key, val, 0);    
        int cmp = key.compareTo(x.key);
        if(cmp < 0) x.left = put(key, val, x.left);
        else if(cmp > 0) x.right = put(key, val, x.right);
        else x.val = val;
        return balance(x);
    }
    
    public void delete(Key key) {
        root = delete(key, root);    
    }
    
    private Node delete(Key key, Node x) {
        if(x == null) return null;
        int cmp = key.compareTo(x.key);
        if(cmp < 0) x.left = delete(key, x.left);
        else if(cmp > 0) x.right = delete(key, x.right);
        else if(x.left != null && x.right != null) {
            Node min = min(x.right);
            x.right = delete(min.key, x.right);
            x.key = min.key;
            x.val = min.val;                    
        } else 
            x = (x.left != null) ? x.left : x.right;
        return balance(x);
    }
    
    private Node balance(Node x) {
        if(t == null) return t;
        if(height(t.left)-height(t.right) > ALLOWED_IMBALANCE) {
            if(height(t.left.left) >= height(t.left.right)) 
                t = rotateWithLeftChild(t);
            else
                t = doubleWithLeftChild(t);                            
        } else {
            if(height(t.right.right) >= height(t.right.left))
                t = rotateWithRightChild(t);
            else       
                t = doubleWithRightChild(t); 
        }   
        t.h = Math.max(height(t.left), height(t.right)) + 1;
        return t;
    }
    
    private Node doubleWithLeftChild(Node x) {
        x.left = rotateWithRightChild(x.left);
        x = rotateWithLeftChild(x);
        return x;    
    }
    
    private Node doubleWithRightChild(Node x) {
        x.right = rotateWithLeftChild(x.right);
        x = rotateWithRightChild(x);
        return x;   
    }
    
    private Node rotateWithLeftChild(Node x) {
        Node l = x.left;
        x.left = l.right;
        l.right = x;
        x.h = Math.max(height(x.left), height(x.right)) + 1;
        l.h = Math.max(height(l.left), height(l.right)) + 1;
        return l;    
    }
    
    private Node rotateWithRightChild(Node x) {
        Node r = x.right;
        x.right = r.left;
        r.left = x;
        x.h = Math.max(height(x.left), height(x.right)) + 1;
        r.h = Math.max(height(r.left), height(h.right)) + 1;
        return r;    
    }
    
    private int height(Node x) {
        if(x == null) return -1;
        return x.h;    
    }
    
    class Node {
        Key key;
        Value val;
        Node left, right;
        int h;    
        
        public Node(Key key, Value val, int h) {
            this.key = key;
            this.val = val;
            this.h = h;        
        }
    }
}

  

posted @ 2022-07-11 11:36  bavaria  阅读(452)  评论(0)    收藏  举报