AVLTree.java

Posted lizhongpingchn

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AVLTree.java相关的知识,希望对你有一定的参考价值。

AVLTree.java


package com.lzp;

/**
* Created by Administrator on 2017/6/3 0003.
*/
public class AVLTree<Item extends Comparable<? super Item>> {
    private static class Node<Item> {
        Node(Item item) {
            this.item = item;
            this.left = left;
            this.right = right;
        }

        Node(Item item, Node<Item> left, Node<Item> right) {
            this.item = item;
            this.left = left;
            this.right = right;
        }

        private Item item;
        private Node<Item> left;
        private Node<Item> right;
        private int height;
    }

    private Node<Item> root;

    public AVLTree() {
        clear();
    }

    public void clear() {
        root = null;
    }

    public boolean isEmpty() {
        return root == null;
    }

    public void insert(Item item) {
        root = insert(item, root);
    }

    private Node<Item> insert(Item item, Node<Item> node) {
        if(node == null)
            return new Node(item, null, null);

        int compareResult = item.compareTo(node.item);
        if(compareResult < 0)
            node.left = insert(item, node.left);
        else if(compareResult > 0)
            node.right = insert(item, node.right);
        else
            ;
        return balance(node); // 平衡树
    }

    private Node<Item> balance(Node<Item> node) {
        if(node == null)
            return node;

        if(height(node.left) - height(node.right) > ALLOWED_IMBALANCE){
            //      A          A
            //      /          /
            //    B          B
            //    /            \
            //  C              C
            if(height(node.left.left) >= height(node.left.right))
                node = rotateWithLeftChild(node);
            else
                node = doubleWithLeftChild(node);
        } else if(height(node.right) - height(node.left) > ALLOWED_IMBALANCE){
            //  A          A
            //    \          \
            //    B          B
            //    /            \
            //  C              C
            if(height(node.right.right) >= height(node.right.left))
                node = rotateWithRightChild(node);
            else
                node = doubleWithRightChild(node);
        }
        node.height = Math.max(height(node.left), height(node.right)) + 1;
        return node;
    }

    // 左左模型
    //      k2        k1
    //    /            \
    //  k1                k2
    // k2 是要旋转的节点
    private Node<Item> rotateWithLeftChild(Node<Item> k2) {
        Node<Item> k1 = k2.left;
        k2.left = k1.right;
        k1.right = k2;
        k2.height = Math.max(height(k2.left), height(k2.right)) + 1;
        k1.height = Math.max(height(k1.left), k2.height) + 1;
        return k1;
    }

    // 右右模型
    //      k1              k2
    //        \            /
    //        k2          k1
    // k1 是要旋转的节点
    private Node<Item> rotateWithRightChild(Node<Item> k1) {
        Node<Item> k2 = k1.right;
        k1.right = k2.left;
        k2.left = k1;
        k1.height = Math.max(height(k1.left), height(k1.right)) + 1;
        k2.height = Math.max(height(k2.right), k1.height) + 1;
        return k2;
    }

    // 左右模型 -- 首先进行儿子k1和孙子k2的右旋转,再进行k3与k2的左旋转
    //      k3                k3
    //      /                /
    //    k1      -->      k2    -->        k2
    //      \              /                /  \
    //      k2            k1                k1  k3
    private Node<Item> doubleWithLeftChild(Node<Item> k3) {
        k3.left = rotateWithRightChild(k3.left);
        return rotateWithLeftChild(k3);
    }

    // 右左模型 -- 首先进行右儿子k3和孙子k2的左旋转,再进行k1与k2的右旋转
    //      k1                k1
    //        \                  \
    //          k3      -->      k2    -->        k2
    //        /                    \              /  \
    //      k2                      k3            k1    k3
    private Node<Item> doubleWithRightChild(Node<Item> k1) {
        k1.right = rotateWithLeftChild(k1.right);
        return rotateWithRightChild(k1);
    }

    public void remove(Item item) {
        root = remove(item, root);
    }

    private Node<Item> remove(Item item, Node<Item> node) {
        if(node == null)
            return node;
        int compareResult = item.compareTo(node.item);
        if(compareResult < 0)
            node.left = remove(item, node.left);
        else if(compareResult > 0)
            node.right = remove(item, node.right);
        else if(node.left != null && node.right != null){
            node.item = findMin(node.right).item;
            node.right = remove(node.item, node.right);
        } else {
            node = (node.left != null) ? node.left : node.right;
        }
        // 正常的二叉树删除 + 再平衡
        return balance(node);
    }

    // AVL平衡树
    // 每个节点的左子树和右子树的高度最多差 1
    private static final int ALLOWED_IMBALANCE = 1;

    // 检查是否是平衡树
    public void checkBlance(){
        checkBlance(root);
    }

    private int checkBlance(Node<Item> node) {
        if(node == null)
            return -1;
        if(node != null){
            int hl = checkBlance(node.left); // 返回左右枝高度
            int hr = checkBlance(node.right);
            if(Math.abs(height(node.left) - height(node.right)) > 1  // 相邻枝高度差大于1
                    || height(node.left) != hl
                    || height(node.right) != hr)
                System.out.println("不平衡");
        }
        return height(node);
    }
    private int height(Node<Item> node){
        return node == null ? -1 : node.height;
    }

    // 最大最小值
    public Item findMin() {
        if (isEmpty())
            throw new RuntimeException("tree is empty");
        return findMin(root).item;
    }

    private Node<Item> findMin(Node<Item> node) {
        if (node == null)
            return node;
        while (node.left != null)
            node = node.left;
        return node;
    }

    public Item findMax() {
        if (isEmpty())
            throw new RuntimeException("tree is empty");
        return findMax(root).item;
    }

    private Node<Item> findMax(Node<Item> node) {
        if(node == null)
            return node;
        else if(node.right == null)
            return node;
        return findMax(node.right);
    }

    public boolean contains(Item item){
        return contains(item, root);
    }

    private boolean contains(Item item, Node<Item> node) {
        while(node != null){
            int compareResult = item.compareTo(node.item);

            if(compareResult < 0)
                node = node.left;
            else if(compareResult > 0)
                node = node.right;
            else
                return true;
        }
        return false;
    }

    public void printTree(){
        if(isEmpty())
            System.out.println("tree is empty");
        else
            printTree(root);
    }

    private void printTree(Node<Item> node) {
        if(node != null){
            printTree(node.left);
            System.out.println(node.item);
            printTree(node.right);
        }
    }

}






































以上是关于AVLTree.java的主要内容,如果未能解决你的问题,请参考以下文章