返回

数据结构之 AVL Tree 二叉平衡树

闲谈

AVL 树概述

AVL 树(Adelson-Velsky and Landis Tree)是一种自平衡二叉搜索树,它能够在插入、删除和查找操作中保持其平衡性。AVL 树的平衡性通过维护每个节点的平衡因子来实现,平衡因子是左子树的高度减去右子树的高度。

AVL 树的性质

  • AVL 树是一种高度平衡的二叉搜索树。
  • AVL 树中每个节点的平衡因子在 -1 和 1 之间。
  • AVL 树的插入、删除和查找操作的时间复杂度为 O(log n)。

AVL 树的插入操作

AVL 树的插入操作与二叉搜索树的插入操作类似,但在插入新节点后,需要对树进行重新平衡,以确保其仍然是平衡的。重新平衡的过程通过旋转操作来实现。

AVL 树的删除操作

AVL 树的删除操作与二叉搜索树的删除操作类似,但在删除节点后,也需要对树进行重新平衡,以确保其仍然是平衡的。重新平衡的过程也通过旋转操作来实现。

AVL 树的查找操作

AVL 树的查找操作与二叉搜索树的查找操作类似,通过比较节点的键值来进行查找。AVL 树的查找操作的时间复杂度为 O(log n)。

AVL 树的 Java 实现

public class AVLTree<K extends Comparable<K>, V> {

    private Node<K, V> root;

    public void insert(K key, V value) {
        root = insert(root, key, value);
    }

    private Node<K, V> insert(Node<K, V> node, K key, V value) {
        if (node == null) {
            return new Node<>(key, value);
        }

        if (key.compareTo(node.key) < 0) {
            node.left = insert(node.left, key, value);
        } else if (key.compareTo(node.key) > 0) {
            node.right = insert(node.right, key, value);
        } else {
            node.value = value;
        }

        updateHeight(node);
        return balance(node);
    }

    public V delete(K key) {
        V value = null;
        root = delete(root, key);
        return value;
    }

    private Node<K, V> delete(Node<K, V> node, K key) {
        if (node == null) {
            return null;
        }

        if (key.compareTo(node.key) < 0) {
            node.left = delete(node.left, key);
        } else if (key.compareTo(node.key) > 0) {
            node.right = delete(node.right, key);
        } else {
            value = node.value;
            if (node.left == null) {
                return node.right;
            } else if (node.right == null) {
                return node.left;
            } else {
                Node<K, V> successor = findMin(node.right);
                node.key = successor.key;
                node.value = successor.value;
                node.right = delete(node.right, successor.key);
            }
        }

        updateHeight(node);
        return balance(node);
    }

    public V find(K key) {
        Node<K, V> node = find(root, key);
        return node == null ? null : node.value;
    }

    private Node<K, V> find(Node<K, V> node, K key) {
        if (node == null) {
            return null;
        }

        if (key.compareTo(node.key) < 0) {
            return find(node.left, key);
        } else if (key.compareTo(node.key) > 0) {
            return find(node.right, key);
        } else {
            return node;
        }
    }

    private Node<K, V> balance(Node<K, V> node) {
        int balanceFactor = getBalanceFactor(node);

        if (balanceFactor > 1) {
            if (getBalanceFactor(node.left) < 0) {
                node.left = leftRotate(node.left);
            }
            return rightRotate(node);
        } else if (balanceFactor < -1) {
            if (getBalanceFactor(node.right) > 0) {
                node.right = rightRotate(node.right);
            }
            return leftRotate(node);
        }

        return node;
    }

    private Node<K, V> leftRotate(Node<K, V> node) {
        Node<K, V> rightChild = node.right;
        node.right = rightChild.left;
        rightChild.left = node;

        updateHeight(node);
        updateHeight(rightChild);

        return rightChild;
    }

    private Node<K, V> rightRotate(Node<K, V> node) {
        Node<K, V> leftChild = node.left;
        node.left = leftChild.right;
        leftChild.right = node;

        updateHeight(node);
        updateHeight(leftChild);

        return leftChild;
    }

    private void updateHeight(Node<K, V> node) {
        node.height = 1 + Math.max(getHeight(node.left), getHeight(node.right));
    }

    private int getHeight(Node<K, V> node) {
        return node == null ? -1 : node.height;
    }

    private int getBalanceFactor(Node<K, V> node) {
        return getHeight(node.left) - getHeight(node.right);
    }

    private Node<K, V> findMin(Node<K, V> node) {
        while (node.left != null) {
            node = node.left;
        }
        return node;
    }

    private static class Node<K, V> {
        private K key;
        private V value;
        private Node<K, V> left;
        private Node<K, V> right;
        private int height;

        public Node(K key, V value) {
            this.key = key;
            this.value = value;
            this.left = null;
            this.right = null;
            this.height = 1;
        }
    }
}

总结

AVL 树是一种高度平衡的二叉搜索树,它能够在插入、删除和查找操作中保持其平衡性。AVL 树的平衡性通过维护每个节点的平衡因子来实现,平衡因子是左子树的高度减去右子树的高度。AVL 树的插入、删除和查找操作的时间复杂度为 O(log n)。