AVL树的Java实现及面试相关

什么是AVL树

AVL树,是最先发明的自平衡二叉树,得名于发明者Adelson-Velsky和Landis。他们在1962年的论文《An algorithm for the organization of information》中发表了它。
AVL树应满足以下条件:
1.首先它是一棵二叉搜索树(BST),即对于任意节点,左节点的值小于根结点的值,右节点的值大于根结点的值。
2.它要么是一棵空树,要么对任意一个节点,其左右子树高度差的绝对值不超过1。
3.对出现不平衡的节点根据不同情况进行旋转。

左旋、右旋balabala(全网最通俗易懂!)

关于左旋右旋已经有许多资料,但这里我力求简单,通俗易懂,讲清楚左旋右旋,在此给出旋转三部曲

Step1:判断类型。有四种类型,RR,LL,RL,LR。它们的含义是出现问题的节点相对于根结点的位置,RR意味着出现问题的节点是根结点右子树的右子树,LR就是根结点左子树的右子树。
Step2:分而治之。对于RR和LL,RL和LR采用不同策略。
Step3:对于RR和LL,采用鸠占鹊巢的方式;对于LR和RL,采用甩锅的方式。

详细细节请见B站视频:AVL树-从入门到入土

Java代码实现

定义节点类

    /**
     * define Node class
     */
    private static class AvlNode<T> {
        T element;
        int height;
        AvlNode<T> left;
        AvlNode<T> right;

        public AvlNode(T element) {
            this(element, null, null);
        }

        public AvlNode(T element, AvlNode<T> left, AvlNode<T> right) {
            this.element = element;
            this.left = left;
            this.right = right;
            this.height = 0;
        }
    }

判断旋转类型

    /**
     * Choose rotate type to achieve balance
     */
    private AvlNode<T> balance(AvlNode<T> t) {
        if (t == null) {
            return t;
        }

        if (height(t.left) - height(t.right) > ALLOWED_IMBALANCE) {
            if (height(t.left.left) >= height(t.left.right)) {
                t = rotateWithLeftChild(t);
            } else {
                t = doubleWithLeftChild(t);
            }
        } else if (height(t.right) - height(t.left) > ALLOWED_IMBALANCE) {
            if (height(t.right.right) >= height(t.right.left)) {
                t = rotateWithRightChild(t);
            } else {
                t = doubleWithRightChild(t);
            }
        }
        t.height = Math.max(height(t.left), height(t.right)) + 1;
        return t;
    }

完整代码

public class AvlTree<T extends Comparable<? super T>> {

    /**
     * define Node class
     */
    private static class AvlNode<T> {
        T element;
        int height;
        AvlNode<T> left;
        AvlNode<T> right;

        public AvlNode(T element) {
            this(element, null, null);
        }

        public AvlNode(T element, AvlNode<T> left, AvlNode<T> right) {
            this.element = element;
            this.left = left;
            this.right = right;
            this.height = 0;
        }
    }

    private static final int ALLOWED_IMBALANCE = 1;

    private AvlNode<T> root;

    public void insert(T x) {
        root = insert(x, root);
    }

    public void remove(T x) {
        root = remove(x, root);
    }

    public T findMin() {
        return findMin(root).element;
    }

    private int height(AvlNode<T> t) {
        return t == null ? -1 : t.height;
    }

    /**
     * insert Node
     *
     * @param x Node for inserting
     * @param t father Node
     */
    private AvlNode<T> insert(T x, AvlNode<T> t) {
        // if root is empty,set x as root
        if (t == null) {
            return new AvlNode(x);
        }
        int compareResult = x.compareTo(t.element);

        // if x < root, put x in the left
        if (compareResult < 0) {
            t.left = insert(x, t.left);
        } else if (compareResult > 0) {
            // if x < root, put x in the right
            t.right = insert(x, t.right);
        } else {
            // if they are equal, update

        }
        return balance(t);
    }

    /**
     * remove Node
     *
     * @param x Node for removing
     * @param t father Node
     */
    private AvlNode<T> remove(T x, AvlNode<T> t) {
        if (t == null) {
            return t;
        }

        int compareResult = x.compareTo(t.element);

        // x < root
        if (compareResult < 0) {
            t.left = remove(x, t.left);
        } else if (compareResult > 0) {
            t.right = remove(x, t.right);
        } else if (t.left != null && t.right != null) {
            // find the min in tne right tree
            t.element = findMin(t.right).element;
            // t的右节点为原来的右节点删去最小值
            t.right = remove(t.element, t.right);
        }
        return balance(t);
    }

    /**
     * find min Node
     */
    private AvlNode<T> findMin(AvlNode<T> t) {
        if (t == null) {
            return null;
        } else if (t.left == null) {
            return t;
        }
        return findMin(t.left);
    }

    /**
     * Choose rotate type to achieve balance
     */
    private AvlNode<T> balance(AvlNode<T> t) {
        if (t == null) {
            return t;
        }

        if (height(t.left) - height(t.right) > ALLOWED_IMBALANCE) {
            if (height(t.left.left) >= height(t.left.right)) {
                t = rotateWithLeftChild(t);
            } else {
                t = doubleWithLeftChild(t);
            }
        } else if (height(t.right) - height(t.left) > ALLOWED_IMBALANCE) {
            if (height(t.right.right) >= height(t.right.left)) {
                t = rotateWithRightChild(t);
            } else {
                t = doubleWithRightChild(t);
            }
        }
        t.height = Math.max(height(t.left), height(t.right)) + 1;
        return t;
    }

    /**
     * RR rotate type
     */
    private AvlNode<T> rotateWithRightChild(AvlNode<T> k2) {
        AvlNode<T> k1 = k2.right;
        k2.right = k1.left;
        k1.left = k2;
        k2.height = Math.max(height(k2.right), height(k2.left)) + 1;
        k1.height = Math.max(height(k1.right), k2.height) + 1;
        return k1;
    }

    /**
     * LL rotate type
     */
    private AvlNode<T> rotateWithLeftChild(AvlNode<T> k2) {
        AvlNode<T> k1 = k2.left;
        k2.left = k1.right;
        k1.right = k2;
        k2.height = Math.max(height(k2.right), height(k2.left)) + 1;
        k1.height = Math.max(height(k1.left), k2.height) + 1;
        return k1;
    }

    // RL rotate type
    private AvlNode<T> doubleWithRightChild(AvlNode<T> k3) {
        k3.right = rotateWithLeftChild(k3.right);
        return rotateWithRightChild(k3);
    }

    // LR rotate type
    private AvlNode<T> doubleWithLeftChild(AvlNode<T> k3) {
        k3.left = rotateWithRightChild(k3.left);
        return rotateWithLeftChild(k3);
    }

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

    /**
     * print Tree
     */
    public void printTree() {
        if (isEmpty()) {
            System.out.println("节点为空");
        } else {
            printTree(root);
        }
    }

    public void printTree(AvlNode<T> t) {
        if (t != null) {
            System.out.print(t.element);
            if (t.left != null) {
                System.out.print(" 左节点" + t.left.element);
            }
            if (t.right != null) {
                System.out.print(" 右节点" + t.right.element);
            }
            System.out.println();
            printTree(t.left);
            printTree(t.right);
        }
    }

    public static void main(String[] args) {
        AvlTree test = new AvlTree();
        test.insert(6);
        test.insert(2);
        test.insert(7);
        test.insert(1);
        test.insert(4);
        test.insert(3);
        test.printTree();
    }
}

测试用例结果
在这里插入图片描述

相关面试题

待补充

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值