平衡二叉树(AVL)代码笔记

来源:互联网 发布:福岛正则 知乎 编辑:程序博客网 时间:2024/05/22 05:31

一棵AVL树是其每个节点的左子树和右子树的高度最多差1的二叉查找树(空树的高度定义为-1)。
重点在于:
插入和删除可能破坏AVL树的平衡特性,需要进行平衡
分为四种情况:
假设重新平衡的节点为a

  • 需要进行单旋转
    (1)a的左儿子的左子树插入
    (2)a的右儿子的右子树插入

  • 需要进行双旋转
    (3)a的左儿子的右子树插入
    (4)a的右儿子的左子树插入

package com.base;public class AvlTree<Item extends Comparable<? super Item>> {    private static class Node<Item> {        Node(Item item) {            this(item, null, null);        }        Node(Item item, Node<Item> lt, Node<Item> rt) {            this.item = item;            this.left = lt;            this.right = rt;            this.height = 0;        }        private Item item;        private Node<Item> left;        private Node<Item> right;        private int height; // 高度    }    private Node<Item> root;    public AvlTree() {        root = null;    }    public void clear() {        root = null;    }    public boolean isEmpty() {        return root == null;    }    /*     * 查找最小     */    public Item min() throws Exception {        if (isEmpty()) // 树为空的情况            throw new Exception();        return min(root).item;    }    private Node<Item> min(Node<Item> t) {        if (t == null)            return t;        while (t.left != null) // 非递归方法            t = t.left;        return t;    }    /*     * 查找最大     */    public Item max() throws Exception {        if (isEmpty())            throw new Exception();        return max(root).item;    }    private Node<Item> max(Node<Item> t) { // 递归方法        if (t.left == null)            return t;        else            return min(t.left);    }    /*     * 是否包含     */    public boolean contains(Item x) {        return contains(x, root);    }    private boolean contains(Item x, Node<Item> t) {        while (t != null) { // 非递归方式            int cmp = x.compareTo(t.item);            if (cmp < 0)                t = t.left;            else if (cmp > 0)                t = t.right;            else                return true; // 匹配        }        return false; // 不包含    }    // 遍历    public void printTree() {        if (isEmpty())            System.out.println("Empty tree");        else            printTree(root);    }    private void printTree(Node<Item> t) { // 左根右--中序        if (t != null) {            printTree(t.left);            System.out.println(t.item);            printTree(t.right);        }    }    /*     * 插入     */    public void insert(Item x) {        root = insert(x, root);    }    private Node<Item> insert(Item x, Node<Item> t) {        if (t == null) // root为null的情况            return new Node<>(x, null, null);        int cmp = x.compareTo(t.item);        if (cmp < 0)            t.left = insert(x, t.left);        else if (cmp > 0)            t.right = insert(x, t.right);        else            ; // 正常二叉树插入        return balance(t); // 再平衡    }    /*     * 删除     */    public void remove(Item x) {        root = remove(x, root);    }    private Node<Item> remove(Item x, Node<Item> t) {        if (t == null)            return t;        int cmp = x.compareTo(t.item);        if (cmp < 0)            t.left = remove(x, t.left);        else if (cmp > 0)            t.right = remove(x, t.right);        else {            if (t.right == null)                return t.left;            if (t.left == null)                return t.right;            t.item = min(t.right).item;            t.right = remove(t.item, t.right);        }        return balance(t); // 正常二叉树删除后再平衡    }    // AVL平衡树    // 每个节点的左子树和右子树的高度最多差 1    private static final int ALLOWED_IMBALANCE = 1;    // 平衡二叉树    private Node<Item> balance(Node<Item> 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;    }    /*     * 二叉树高度--树null,高度为-1     */    private int height(Node<Item> t) {        return t == null ? -1 : t.height;    }    /*     * 把左边的树变成右边的树     */    private Node<Item> rotateWithLeftChild(Node<Item> k2) {        Node<Item> k1 = k2.left;        k2.left = k1.right;        k1.right = k2;  // k1 变为根        k2.height = Math.max(height(k2.left), height(k2.right)) + 1; // k2 高度        k1.height = Math.max(height(k1.left), k2.height) + 1;   // 根k1 高度        return 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;    }    /*     * 左儿子的右子树     */    private Node<Item> doubleWithLeftChild(Node<Item> k3) {        k3.left = rotateWithRightChild(k3.left);        return rotateWithLeftChild(k3);    }    /*     * 右儿子的左子树     */    private Node<Item> doubleWithRightChild(Node<Item> k1) {        k1.right = rotateWithLeftChild(k1.right);        return rotateWithRightChild(k1);    }    /*     * 检查二叉树是否平衡     */    public void checkBalance() {        checkBalance(root);    }    private int checkBalance(Node<Item> t) {        if (t == null)            return -1;        if (t != null) {            int hl = checkBalance(t.left);            int hr = checkBalance(t.right);            if (Math.abs(height(t.left) - height(t.right)) > 1 || height(t.left) != hl || height(t.right) != hr)                System.out.println("不平衡");        }        return height(t);    }}

一点一点补充吧

-

1 0
原创粉丝点击