一天一个算法——>平衡二叉树的插入

package tree;

/**
 * 平衡二叉树(AVL树)
 * 这里只模拟int类型实现,如果需要其他类型,请将int类型修改为泛型,并实现extends Comparable接口,方便比较
 * 动态模拟实现:https://www.cs.usfca.edu/~galles/visualization/AVLtree.html
 * GitHub地址:https://github.com/hack-feng/algorithm
 */
public class AVLTree{

    private Node root;

    static class Node{
        int data;

        Node left;

        Node right;

        int height;

        Node(Node left, Node right, int data) {
            this.left = left;
            this.right = right;
            this.data = data;
            this.height = 0;
        }
    }


    // 插入节点
    private void insert(int data){
        root = insert(data, root);
    }

    private Node insert(int data, Node node){
        if(node == null){
            Node returnNode =  new Node(null, null, data);
            // 新创建的树,高度默认为1
            returnNode.height = 1;
            return returnNode;
        }else{
            // 如果root.data的值大于data, 则在左子树上插入,否则在右子树上插入
            if(node.data > data){
                node.left = insert(data, node.left);
                // 判断树是否失衡,失衡需要旋转
                if(getHeight(node.left) > getHeight(node.right) + 1){

                    // 判断进行两次旋转还是一次旋转
                    if(node.left.data > data){
                        //(LL)一次旋转, 右旋
                        node = LL(node);
                    }else{
                        //(LR)两次旋转, 先左旋,再右旋
                        node = LR(node);
                    }
                }
            }else{
                node.right = insert(data, node.right);
                // 判断树是否失衡,失衡需要旋转
                if(getHeight(node.right) > getHeight(node.left) + 1){
                    // 判断进行两次旋转还是一次旋转
                    if(node.right.data > data){
                        //(RL)两次旋转,先右旋,再左旋
                        node = RL(node);
                    }else{
                        //(RR)一次旋转,左旋
                        node = RR(node);
                    }
                }
            }
            // 重新计算树的高度
            node.height = setHeight(node);
            return node;
        }
    }

    // 左左情况, 进行一次右旋
    private Node LL(Node node){
        Node leftNode = node.left;
        node.left = leftNode.right;
        leftNode.right = node;

        //重新计算高度
        node.height = setHeight(node);
        leftNode.height = setHeight(leftNode);
        return leftNode;
    }

    // 左右情况, 先进行左旋,再进行一次右旋
    private Node LR(Node node){
        node.left = RR(node.left);
        node = LL(node);
        return node;
    }

    // 右右情况, 进行一次左旋
    private Node RR(Node node){
        Node rightNode = node.right;
        node.right = rightNode.left;
        rightNode.left = node;

        //重新计算高度
        node.height = setHeight(node);
        rightNode.height = setHeight(rightNode);
        return rightNode;
    }

    // 右左情况,先进行右旋,再进行一次左旋
    private Node RL(Node node){
        node.right = LL(node.right);
        node = RR(node);
        return node;
    }

    // 获取树的高度
    private int getHeight(Node node){
        return node == null ? 0 : node.height;
    }

    // 重新计算树的高度
    private int setHeight(Node node){
        return Math.max(getHeight(node.left), getHeight(node.right)) + 1;
    }

    // 打印节点
    private void printNode(Node root){
        if(root != null){
            printNode(root.left);
            System.out.println(root.data);
            printNode(root.right);
        }
    }

    public static void main(String [] args){
//        int[] dataArray = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9};
        int[] dataArray = new int[]{2, 8, 5, 6, 7, 4, 3, 1, 9};
        AVLTree tree = new AVLTree();
        for (int i : dataArray) {
            tree.insert(i);
        }
        tree.printNode(tree.root);
    }
}

你可能感兴趣的:(算法)