• 平衡二叉树


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

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

    于是,就涉及两个问题。

    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);
        }
    }

  • 相关阅读:
    萨卡斯指法
    香港保险
    数据分析,了解行业
    数据分析师
    黑盒测试方法
    web系统的常用功能测试
    linux-磁盘问题
    mysql连表查询
    mysql模糊查询
    MySQL 数据类型
  • 原文地址:https://www.cnblogs.com/rixiang/p/4681364.html
Copyright © 2020-2023  润新知