AVL树(平衡二叉树)

AVL树本质上是一颗二叉查找树,但是它又具有以下特点:

1、   它是一棵空树或它的左右两个子树的高度差的绝对值不超过1

2、   左右两个子树都是一棵平衡二叉树。

AVL树解决了普通二叉查找树演化为线性导致线性查找时间问题

AVL树平衡的操作主要有:

1、左-左型:做右旋。

2、右-右型:做左旋转。

3、左-右型:先做左旋,后做右旋。

4、右-左型:先做右旋,再做左旋。

右旋:把左孩子变成父节点,原来的父节点变成左孩子的右孩子,见下图(左左型)。

平衡二叉树,B树              平衡二叉树,B树

左旋:把右孩子变成父节点,原来的父节点变成右孩子的左孩子,见下图(右右型)。

平衡二叉树,B树              平衡二叉树,B树

下面是右左型的平衡操作

平衡二叉树,B树         平衡二叉树,B树       平衡二叉树,B树

实现代码(没有编写测试用例,可能会有一些边界未处理问题)

public class AVL {

    
    public class AVLNode{
        
        int height;
        AVLNode leftChild;
        AVLNode rightChild;
        AVLNode parent;
        int value;
        
    }
    
    public int getHeight(AVLNode node) {
        
        if (node == null) {
            return 0;
        }else {
            return node.height;
        }
    }
    
    /**
     * 左左型不平衡,进行右旋操作
     * @param LL_type_node
     */
    public void R_Rotate(AVLNode LL_type_node) {
        
        if (LL_type_node != null) {
            
            AVLNode left = LL_type_node.leftChild; // 取出要旋转节点的左孩子
            AVLNode parent = LL_type_node.parent;  // 取出要旋转节点的父节点
            
            LL_type_node.leftChild = left.rightChild; // 左孩子的右孩子变成父节点的左孩子
            left.rightChild.parent = LL_type_node;
        
            left.rightChild = LL_type_node; // 左孩子的右节点变为其原来的父节点
            
            // 更新父节点
            LL_type_node.parent = left;
            left.parent = parent;
            
            // 检查原来要旋转节点是其父节点的左孩子还是右孩子
            if (parent.leftChild == LL_type_node) {
                parent.leftChild = left;
            }else if (parent.rightChild == LL_type_node) {
                parent.rightChild = left;
            }
            
            LL_type_node.height = Math.max(getHeight(LL_type_node.leftChild), 
                    getHeight(LL_type_node.rightChild)) + 1;
            left.height = Math.max(getHeight(left.leftChild), 
                    getHeight(left.rightChild)) + 1;
            parent.height = Math.max(getHeight(parent.leftChild), 
                    getHeight(parent.rightChild)) + 1;
        }
        
    }
    
    /**
     * 右右型不平衡,进行左旋操作
     * @param LL_type_node
     */
    public void L_Rotate(AVLNode RR_type_node) {
        
        if (RR_type_node != null) {
            
            AVLNode right = RR_type_node.leftChild; // 取出要旋转节点的右孩子
            AVLNode parent = RR_type_node.parent;  // 取出要旋转节点的父节点
            
            RR_type_node.rightChild = right.leftChild; // 右孩子的左孩子变成父节点的右孩子
            right.leftChild.parent = RR_type_node;
        
            right.leftChild = RR_type_node; // 左孩子的右节点变为其原来的父节点
            
            // 更新父节点
            RR_type_node.parent = right;
            right.parent = parent;
            
            // 检查原来要旋转节点是其父节点的左孩子还是右孩子
            if (parent.leftChild == RR_type_node) {
                parent.leftChild = right;
            }else if (parent.rightChild == RR_type_node) {
                parent.rightChild = right;
            }
            
            RR_type_node.height = Math.max(getHeight(RR_type_node.leftChild), 
                    getHeight(RR_type_node.rightChild)) + 1;
            right.height = Math.max(getHeight(right.leftChild), 
                    getHeight(right.rightChild)) + 1;
            parent.height = Math.max(getHeight(parent.leftChild), 
                    getHeight(parent.rightChild)) + 1;
        }
    }

    /**
     * 左右型,先左旋,后右旋
     * @param LR_type_node
     */
    public void L_R_Rotate(AVLNode LR_type_node) {
        if (LR_type_node != null) {
            L_Rotate(LR_type_node.leftChild);
            R_Rotate(LR_type_node);
        }
    }
    
    /**
     * 左右型,先右旋,后左旋
     * @param LR_type_node
     */
    public void R_L_Rotate(AVLNode RL_type_node) {
        if (RL_type_node != null) {
            R_Rotate(RL_type_node.rightChild);
            L_Rotate(RL_type_node);
        }
    }
    
    public AVLNode insertAVLTree(AVLNode root, AVLNode toInsert) {
        
        AVLNode rtRoot = root;
        
        if (toInsert != null) {
            if (root != null) {
                
                if (root.value > toInsert.value) {
                    rtRoot.leftChild = insertAVLTree(root.leftChild, toInsert);
                    //插入后看看是否需要调整
                    if (getHeight(rtRoot.leftChild) - 
                            getHeight(rtRoot.rightChild) == 2) {
                        // 左左型,进行右旋
                        if (toInsert.value < rtRoot.leftChild.value) {
                            R_Rotate(rtRoot);
                        }else {
                            // 左右型
                            L_R_Rotate(rtRoot);
                        }
                    }
                }else if (root.value < toInsert.value) {
                
                    rtRoot.rightChild = insertAVLTree(root.rightChild, toInsert);
                    //插入后看看是否需要调整
                    if (getHeight(rtRoot.rightChild) - 
                            getHeight(rtRoot.leftChild) == 2) {
                        // 右右型,进行左旋
                        if (toInsert.value > rtRoot.rightChild.value) {
                            L_Rotate(rtRoot);
                        }else {
                            // 右左型
                            R_L_Rotate(rtRoot);
                        }
                    }
                }
            }else {
                rtRoot = toInsert;
            }
        }
        rtRoot.height = Math.max(getHeight(rtRoot.leftChild), 
                getHeight(rtRoot.rightChild)) + 1;
        return rtRoot;
    }
    
    public void deleteNode(AVLNode root, int value) {
        
        if (root != null) {
            if (value < root.value) {
                deleteNode(root.leftChild, value);
                int lh = getHeight(root.leftChild);
                int rh = getHeight(root.rightChild);
                
                if (rh - lh == 2) {
                    if(getHeight(root.rightChild.rightChild) > 
                    getHeight(root.rightChild.leftChild)){
                        // 右右型
                        L_Rotate(root);
                    }else{
                        // 右左型
                        R_L_Rotate(root);
                    }
                }
                
            }else if (value > root.value) {
                deleteNode(root.rightChild, value);
                int lh = getHeight(root.leftChild);
                int rh = getHeight(root.rightChild);
                
                if (lh - rh == 2) {
                    if(getHeight(root.leftChild.leftChild) > 
                    getHeight(root.leftChild.rightChild)){
                        // 左左型
                        R_Rotate(root);
                    }else{
                        // 左右型
                        L_R_Rotate(root);
                    }
                }
            }else {
                
                AVLNode toDeleteParent = root.parent;
                
                if (root.leftChild == null) {
                    /* 要删除节点的左子树为空,那么该节点可以直接删除而不用找后继节点(因为后继就是它的右
                     * 孩子,如果它的右孩子也为空,那说明它是个叶子节点,可直接删)
                     */
                    if (root == toDeleteParent.leftChild) {
                        toDeleteParent.leftChild = root.rightChild;
                        if (toDeleteParent.leftChild != null) {
                            toDeleteParent.leftChild.parent = toDeleteParent;
                        }
                    }else {
                        toDeleteParent.rightChild = root.rightChild;
                        if (toDeleteParent.rightChild != null) {
                            toDeleteParent.rightChild.parent = toDeleteParent;
                        }
                    }
                }else if (root.rightChild == null) {
                    /* 要删除节点的右子树为空,那么该节点可以直接删除而不用找后继节点(因为后继就是它的父
                     * 节点,如果它的左孩子也为空,那说明它是个叶子节点,可直接删)
                     */
                    if (root == toDeleteParent.leftChild) {
                        toDeleteParent.leftChild = root.leftChild;
                        if (toDeleteParent.leftChild != null) {
                            toDeleteParent.leftChild.parent = toDeleteParent;
                        }
                    }else {
                        toDeleteParent.rightChild = root.leftChild;
                        if (toDeleteParent.rightChild != null) {
                            toDeleteParent.rightChild.parent = toDeleteParent;
                        }
                    }
                }else {
                    int next = getHeight(root);
                    root.value = next; // 用后继代替待删除节点
                    deleteNode(root.rightChild, next); // 删除后继
                    
                    int lh = getHeight(root.leftChild);
                    int rh = getHeight(root.rightChild);
                    
                    if (lh - rh == 2) {
                        if(getHeight(root.leftChild.leftChild) > 
                        getHeight(root.leftChild.rightChild)){
                            // 左左型
                            R_Rotate(root);
                        }else{
                            // 左右型
                            L_R_Rotate(root);
                        }
                    }
                }
            }
            
            root.height = Math.max(getHeight(root.leftChild), 
                    getHeight(root.leftChild)) + 1;
        }
        
    }
    
    /**
     * 取得当前节点的后继
     * @param currentNode
     * @return
     */
    public int getNextNodeValue(AVLNode currentNode) {
        if ((currentNode = currentNode.rightChild) != null) {
            
            while(currentNode.leftChild != null){
                currentNode = currentNode.leftChild;
            }
        }
        
        return currentNode.value;
    }
    
}
View Code

相关文章: