My集合框架第三弹 AVL树

旋转操作:

由于任意一个结点最多只有两个儿子,所以当高度不平衡时,只可能是以下四种情况造成的:

1. 对该结点的左儿子的左子树进行了一次插入。

2. 对该结点的左儿子的右子树进行了一次插入。

3. 对该结点的右儿子的左子树进行了一次插入。

4. 对该结点的右儿子的右子树进行了一次插入。

向AVL树插入节点后,需要让AVL树重新平衡

step1:从插入节点向根节点溯源,观察是否存在不平衡节点(左右子树高度差),
    if(不存在),return
    else  step2
step2:标记不平衡节点为K1
    if(K1.left.depth>K1.right.depth)      step3;
    else        step4;
step3:根据插入值和K2元素值比较
    if(K3<K2.element)     情形1;
    else              情形2;
step4:if(K3<K2.element)      情形3;
    else              情形4;

情形1:

K1为不平衡节点,K3为插入节点

经过一次单旋转,变为

 

代码实现

public AvlNode<AnyType> rotateWithLeftChild(AvlNode<AnyType> K1){
		AvlNode<AnyType> K2 = K1.left;
		K1.left = K2.right;
		K2.right = K1;
		//更新高度(省略)
		return K2;
}

 注意:一定要更新父节点的左子树的指向

情形4与情形1对称,不在赘述

情形2:对应于左右双旋

为了描述清楚,即使树中的节点为null,仍然标记为字母ABCD

K1为不平衡节点

step1:K2

以K2为不平衡节点左旋,得到

继续以K1为不平衡节点右旋,得到平衡

代码:

public AvlNode<AnyType> doubleWithLeftChild(AvlNode<AnyType> K1){
		K1.left = rotateWithRightChild(K1.left);
		return rotateWithLeftChild(K1);
}

 情形3与之对称

 

部分代码如下:

package com.wpr.collection;


public class AVLTree<AnyType extends Comparable<? super AnyType>> {
    private static class AVLNode<AnyType> {
        AnyType element;
        AVLNode<AnyType> left;
        AVLNode<AnyType> right;
        int height;
        
        public AVLNode(AnyType element) {
            this(element,null,null);
        }

        public AVLNode(AnyType element2,AVLNode<AnyType> left, AVLNode<AnyType> right) {
            this.element = element2;
            this.left = left;
            this.right = right;
        }
        
    }
    
    AVLNode<AnyType> root;
    public void insert(AnyType x){
        if(x!=null)
            root = insert(x,root);
    }
    
    private AVLNode<AnyType> insert(AnyType x,AVLNode<AnyType> t){
        if(t==null)
            return new AVLNode<AnyType>(x);
        
        int compareResult = x.compareTo(t.element);
        
        if(compareResult<0){
            //在左子树上插入
            t.left = insert(x,t.left);
            if(height(t.left)-height(t.right)==2){
            //存在不平衡节点t
                if(x.compareTo(t.left.element)<0)
                    //情形一
                    t = rotateWithLeftChild(t);
                else
                    //情形二
                    t = doubleWithLeftChild(t);
            }
        }else if(compareResult>0){
            t.right = insert(x,t.right);
            if(height(t.right)-height(t.left)==2){
                //存在不平衡节点
                if(x.compareTo(t.right.element)>0)
                //情形三
                t = rotateWithRightChild(t);
                else
                //情形四
                t = doubleWithRightChild(t);
            }
        }
        t.height = Math.max(height(t.left), height(t.right))+1;
        return t;
    }
    
    private AVLNode<AnyType> doubleWithRightChild(AVLNode<AnyType> t) {
        t.right = rotateWithLeftChild(t.right);
        return rotateWithRightChild(t);
    }

    private AVLNode<AnyType> rotateWithRightChild(AVLNode<AnyType> t) {
        AVLNode<AnyType> temp = t.right;
        t.right = temp.left;
        temp.left =t;
        t.height = Math.max(height(t.left), height(t.right))+1;
        temp.height = Math.max(height(temp.left), height(temp.right))+1;
        return temp;
    }

    private AVLNode<AnyType> doubleWithLeftChild(AVLNode<AnyType> t) {
        t.left = rotateWithRightChild(t.left);
        return rotateWithLeftChild(t);
    }

    private AVLNode<AnyType> rotateWithLeftChild(AVLNode<AnyType> t) {
        AVLNode<AnyType> temp = t.left;
        t.left = temp.right;
        temp.right = t;
        t.height = Math.max(height(t.left), height(t.right))+1;
        temp.height = Math.max(height(temp.left), height(temp.right))+1;
        return temp;
    }

    private int height(AVLNode<AnyType> t){
        return t==null?-1:t.height;
    }
    
    /**
     * 打印树
     */
    public void printTree(){
        if(isEmpty()){
            System.out.println("Empty Tree");
        }
        printTree(root);
    }
    /**
     * 中序遍历树
     * @param t
     */
    private void printTree(AVLNode<AnyType> t) {
        if(t!=null){
            System.out.print(t.element+"\t");
            printTree(t.left);
            printTree(t.right);
        }
    }
    
    public boolean isEmpty() {
        return root == null;
    }
    
}

 上面AVLNode记录的是树的高度,参考了别人的文章,可以改成平衡因子。。

    http://blog.csdn.net/ljianhui/article/details/9137177

    http://blog.csdn.net/ljianhui/article/details/9204667

 

posted @ 2015-03-04 09:09  卡卡西sir  阅读(139)  评论(0编辑  收藏  举报