平衡二叉树

 首先讲一下平衡二叉树的基本思路,算是一种总结。

平衡二叉树是在二叉排序树的基础上产生的,如果你不了解二叉排序树,请先看看《算法导论》。
由于二叉排序树有时会产生不平衡的情况,于是需要设计算法使不平衡的情况从新归为平衡。

于是,就涉及两个问题。

1,如何发现不平衡
      这里为二叉树加入高度的概念,当左子树和右子树高度差为2时,为不平衡。于是调整该子树。
      在代码的具体实现中,就体现在增加节点,和删除节点后,判断二叉树不是否平衡,若不平衡,哪里开始不平衡。
      这需要在递归的过程中进行判断,例如插入节点时,需要在递归的过程中寻找插入位置。而在退出递归时,每退出一层,都会在该层递归函数尾,重新设定该节点高度(叶子节点为1,以上每一层加一,且父亲节点高度取子节点高度最大值加一),并判断该子树是否平衡。不平衡则调整。这样的方式,在递归(插入,删除操作),以及一层层退出递归(调整二叉树)的过程中,实现平衡。

2,如何重新变为平衡 
      四种旋转方式:
图取自http://www.cnblogs.com/skywang12345/p/3577479.html

 

I will wrote code of AVLTree carefully,to wrote the best of java code.

and I will apply java's Generic,and the principle of "Interface oriented programming" by the structure of three layerings of entity,service and serviceimpl.

 具体实现,参照下文代码。

实体类代码,基本二叉树结构外加入height:

 1 /**
 2  * @ClassName: AVLNode
 3  * @author Hyuga
 4  * @date 2015-12-29 下午1:58:39
 5  * @Description: Entity class of AVL tree
 6  * @version 1.0
 7  */
 8 public class AVLNode<T extends Comparable<T>>
 9 {
10 
11     // Value of node
12     private T data;
13 
14     // Left child
15     private AVLNode<T> leftChild;
16 
17     // Right child
18     private AVLNode<T> rightChild;
19     
20     //Height of node
21     private Integer height;
22 
23     public T getData()
24     {
25         return data;
26     }
27 
28     public void setData(T data)
29     {
30         this.data = data;
31     }
32 
33     public AVLNode<T> getLeftChild()
34     {
35         return leftChild;
36     }
37 
38     public void setLeftChild(AVLNode<T> leftChild)
39     {
40         this.leftChild = leftChild;
41     }
42 
43     public AVLNode<T> getRightChild()
44     {
45         return rightChild;
46     }
47 
48     public void setRightChild(AVLNode<T> rightChild)
49     {
50         this.rightChild = rightChild;
51     }
52 
53     public Integer getHeight()
54     {
55         return height;
56     }
57 
58     public void setHeight(Integer height)
59     {
60         this.height = height;
61     }

面向接口编程,接口列表:

/**
* @ClassName: AVLService
* @Description: Service class of avl tree
* @author           Hyuga
* @date                2015-12-29 - 2015-12-31
* @version          1.0
 * @param <T>
 */
public interface AVLService<T extends Comparable<T>>
{
    /**
     * add node to AVL tree,return the information of execution
     */
    public AVLNode<T> addNode(AVLNode<T> node,T value);
    
    /**
     * delete node from AVL tree,return the information of execution
     */
    public AVLNode<T> deleteNode(AVLNode<T> root,AVLNode<T> node,T value);
    /**
     * search the node of value given 
     */
    public AVLNode<T> searchNode(AVLNode<T> root,T value);
    
    /**
     * level traverse
     */
    public void levelTraverse(AVLNode<T> root);
    
    /**
     * LDR
     */
    public AVLNode<T> inOrderTraverse(AVLNode<T> root);
    
}

具体实现类
对外方法:
       插入节点:addNode
       删除节点   deleteNode
       层次遍历   levelTraverse
       中序遍历   inOrderTraverse
       查找结点   searchNode
内部方法
       四种旋转方式 rightRightRotation
                             leftLeftRotation
                             leftRightRotation
                             rightLeftRotation
       求两int数中大值   max
       返回左子树和右子树中高的大值+1
                             getMaxHeight
       或取子树最大节点--最右边 的父节点
                              getParentOfMax
        将找到的节点删除
                              remove
        判断是LL旋转还是LR旋转,并旋转
                              LL_LR
        判断是RR旋转还是RL旋转,并旋转
                              RR_RL

/**
 * @ClassName: AVLServiceImpl
 * @Description: Service impl class of avl tree
 * @author Hyuga
 * @date 2015-12-29 - 2015-12-31
 * @version 1.0
 * @param <T>
 */
public class AVLServiceImpl<T extends Comparable<T>> implements AVLService<T>
{
    /**
     * insert a node to AVL tree.
     */
    @Override
    public AVLNode<T> addNode(AVLNode<T> root, T value)
    {
        if (null == value)
        {
            System.out.println("Please insert valid value");
            return null;
        }
        if (null == root)
        {
            root = new AVLNode<T>();
            root.setData(value);
            root.setHeight(0);
        }
        else
        {
            int cmp = root.getData().compareTo(value);
            AVLNode<T> leftChild = root.getLeftChild();
            AVLNode<T> rightChild = root.getRightChild();
            if (cmp == 0)
                System.out.println("You should not add duplicate node");
            if (cmp < 0) // insert to right
            {
                root.setRightChild(addNode(rightChild, value));
                if (getHeight(rightChild) - getHeight(leftChild) == 2)
                {
                    root = RR_RL(root);
                }
            }
            else
            // insert to left
            {
                root.setLeftChild(addNode(leftChild, value));
                if (getHeight(leftChild) - getHeight(rightChild) == 2)
                {
                    root = LL_LR(root);
                }
            }
        }
        root.setHeight(getMaxHeight(root));
        return root;
    }

    @Override
    public AVLNode<T> searchNode(AVLNode<T> root, T value)
    {
        if (null == root)
        {
            System.out.println("Node does not exist");
            return null;
        }
        int cmp = root.getData().compareTo(value);
        if (value == root.getData())
            return root;
        if (cmp > 0)
            return searchNode(root.getLeftChild(), value);
        else
            return searchNode(root.getRightChild(), value);
    }

    /**
     * find and delete a node
     */
    @Override
    public AVLNode<T> deleteNode(AVLNode<T> parent, AVLNode<T> node, T value)
    {
        if (null == value)
        {
            System.out.println("Please insert valid value");
            return null;
        }
        else if (null == node)
        {
            System.out.println("Tree does not exist");
        }
        else
        {
            int cmp = node.getData().compareTo(value);
            if (cmp == 0)
            {
                node = remove(parent, node, value);
            }
            else if (cmp < 0)
            {
                deleteNode(node, node.getRightChild(), value);
                if (getHeight(node.getLeftChild())
                        -  getHeight(node.getRightChild()) == 2)
                {
                    node = LL_LR(node);
                }
            }
            else
            {
                deleteNode(node, node.getLeftChild(), value);
                if (getHeight(node.getRightChild()) 
                        - getHeight(node.getLeftChild()) == 2)
                {
                    node = RR_RL(node);
                }
            }
        }
        node.setHeight(getMaxHeight(node));
        return node;
    }
    
    /**
     * LL or LR
     */
    private AVLNode<T> LL_LR(AVLNode<T> root)
    {
        AVLNode<T> temp = root.getLeftChild().getRightChild();
        if(null == temp ||
                (null == temp.getRightChild()&&null == temp.getLeftChild()))
            return leftLeftRotation(root);
        else
            return leftRightRotation(root);
    }
    
    /**
     * RR or RL
     */
    private AVLNode<T> RR_RL(AVLNode<T> root)
    {
        AVLNode<T> temp = root.getRightChild().getLeftChild();
        if(null == temp||
                (null == temp.getLeftChild() && null == temp.getRightChild()))
            return rightRightRotation(root);
        else
            return rightLeftRotation(root);
    }

    /**
     * remove the node which found
     */
    private AVLNode<T> remove(AVLNode<T> parent, AVLNode<T> node, T value)
    {
        if (null == node.getLeftChild() && null == node.getRightChild())
        {
            if (parent.getData().compareTo(value) > 0)
                parent.setLeftChild(null);
            else
                parent.setRightChild(null);
            node = parent;
        }
        else if (null == node.getLeftChild())
        {
            if (parent.getData().compareTo(value) > 0)
                parent.setLeftChild(node.getRightChild());
            else
                parent.setRightChild(node.getRightChild());
        }
        else if (null == node.getRightChild())
        {
            if (parent.getData().compareTo(value) > 0)
                parent.setLeftChild(node.getLeftChild());
            else
                parent.setRightChild(node.getLeftChild());
        }
        else
        {
            // either leftChild or rightChild is not null,get the max node of
            // left child tree to be the root
            AVLNode<T> parentOfMax;
            if (null == node.getLeftChild().getRightChild())
            {
                node.getLeftChild().setRightChild(node.getRightChild());
                node = node.getLeftChild();
                if(parent.getData().compareTo(node.getData())<0)
                    parent.setRightChild(node);
                else
                    parent.setLeftChild(node);
            }
            else
            {
                // get the parent of the max node of the leftchild of root.
                parentOfMax = getParentOfMax(node.getLeftChild());
                AVLNode<T> temp = parentOfMax.getRightChild();
                // remove the root and set the max node of the leftchild to be
                // the root
                temp.setLeftChild(node.getLeftChild());
                temp.setRightChild(node.getRightChild());
                parentOfMax.setRightChild(null);
                node = temp;
            }
        }
        return node;
    }

    /**
     * get the parent of max node
     */
    private AVLNode<T> getParentOfMax(AVLNode<T> root)
    {
        if (null == root.getRightChild().getRightChild()
                || null == root.getRightChild())
            return root;
        else
            return getParentOfMax(root.getRightChild());
    }

    private int getHeight(AVLNode<T> root)
    {
        if (null == root)
            return 0;
        return root.getHeight();
    }

    /**
     * get max value of two int
     */
    private int max(int int1, Integer int2)
    {
        if (int1 >= int2)
            return int1;
        return int2;
    }

    private int getMaxHeight(AVLNode<T> root)
    {
        int leftHeight = (null == root.getRightChild() ? 0 : root
                .getRightChild().getHeight());
        int rightHeight = (null == root.getLeftChild() ? 0 : root
                .getLeftChild().getHeight());
        return max(leftHeight, rightHeight) + 1;
    }

    @Override
    public void levelTraverse(AVLNode<T> root)
    {
        if (null == root)
            return;
        Queue<AVLNode<T>> queue = new LinkedList<AVLNode<T>>();
        queue.add(root);
        while (!queue.isEmpty())
        {
            AVLNode<T> temp = queue.peek().getLeftChild();
            if (null != temp)
                queue.add(temp);
            temp = queue.peek().getRightChild();
            if (null != temp)
                queue.add(temp);
            System.out.print(queue.poll().getData() + " ");
        }
    }
    
    @Override
    public AVLNode<T> inOrderTraverse(AVLNode<T> root) 
    {
        if(null == root)
            return null;
        inOrderTraverse(root.getLeftChild());
        System.out.print(root.getData() + " ");
        inOrderTraverse(root.getRightChild());
        return root;
    }

    private AVLNode<T> leftLeftRotation(AVLNode<T> node)
    {
        AVLNode<T> temp = node.getLeftChild();
        node.setLeftChild(temp.getRightChild());
        temp.setRightChild(node);
        node.setHeight(max(getHeight(node.getLeftChild()),
                getHeight(node.getRightChild())) + 1);
        temp.setHeight(max(getHeight(temp.getLeftChild()), node.getHeight()) + 1);
        return temp;
    }

    private AVLNode<T> leftRightRotation(AVLNode<T> node)
    {
        node.setLeftChild(rightRightRotation(node.getLeftChild()));
        return leftLeftRotation(node);
    }

    private AVLNode<T> rightLeftRotation(AVLNode<T> node)
    {
        node.setRightChild(leftLeftRotation(node.getRightChild()));
        return rightRightRotation(node);
    }

    private AVLNode<T> rightRightRotation(AVLNode<T> node)
    {
        AVLNode<T> temp = node.getRightChild();
        node.setRightChild(temp.getLeftChild());
        temp.setLeftChild(node);
        node.setHeight(max(getHeight(node.getLeftChild()),
                getHeight(node.getRightChild())) + 1);
        temp.setHeight(max(getHeight(temp.getRightChild()), node.getHeight()) + 1);
        return temp;
    }

}

最后测试代码及结果:

public class AVLTest 
{
    /**
     * test code
     */
    public static void main(String[] args) 
    {
        System.out.println("Algorithm of AVLBinaryTree by 无名.2015.12.31");
        AVLNode<Integer> root = new AVLNode<Integer>();
        AVLService<Integer> avlService = new AVLServiceImpl<Integer>();
        root.setData(12);
        root.setHeight(0);
        System.out.println("insert,13,15,17,19,20");
        System.out.println("inserting...");
        root = avlService.addNode(root, 13);
        root = avlService.addNode(root, 15);
        root = avlService.addNode(root, 17);
        root = avlService.addNode(root, 19);
        root = avlService.addNode(root, 20);
        System.out.println("inorder traverse:");
        avlService.inOrderTraverse(root);
        System.out.println();
        System.out.println("level traverse:");
        avlService.levelTraverse(root);
        System.out.println();
        System.out.println("delete 17 and level traverse:");
        root = avlService.deleteNode(root, root, 17);
        avlService.levelTraverse(root);
        System.out.println();
        System.out.println("delete 19,20 and level traverse:");
        root = avlService.deleteNode(root, root, 19);
        root = avlService.deleteNode(root, root, 20);
        avlService.levelTraverse(root);
    }
}

原文地址:https://www.cnblogs.com/rixiang/p/4681364.html