zoukankan      html  css  js  c++  java
  • 平衡二叉树

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

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

    于是,就涉及两个问题。

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

  • 相关阅读:
    www.insidesql.org
    kevinekline----------------- SQLSERVER MVP
    Sys.dm_os_wait_stats Sys.dm_performance_counters
    如何使用 DBCC MEMORYSTATUS 命令来监视 SQL Server 2005 中的内存使用情况
    VITAM POST MORTEM – ANALYZING DEADLOCKED SCHEDULERS MINI DUMP FROM SQL SERVER
    Cargo, Rust’s Package Manager
    建筑识图入门(初学者 入门)
    Tracing SQL Queries in Real Time for MySQL Databases using WinDbg and Basic Assembler Knowledge
    Microsoft SQL Server R Services
    The Rambling DBA: Jonathan Kehayias
  • 原文地址:https://www.cnblogs.com/rixiang/p/4681364.html
Copyright © 2011-2022 走看看