package com.googlecode.totallylazy.collections; import com.googlecode.totallylazy.functions.Function1; import com.googlecode.totallylazy.Pair; import com.googlecode.totallylazy.predicates.Predicate; import com.googlecode.totallylazy.Unchecked; import com.googlecode.totallylazy.comparators.Comparators; import java.util.Comparator; import java.util.NoSuchElementException; import static com.googlecode.totallylazy.Unchecked.cast; public interface AVLTree<K, V> extends TreeMap<K, V> { int height(); int balance(); @Override AVLTree<K, V> empty(); @Override AVLTree<K, V> cons(Pair<K, V> head); @Override AVLTree<K, V> tail() throws NoSuchElementException; @Override AVLTree<K, V> insert(K key, V value); @Override AVLTree<K, V> delete(K key); @Override Pair<AVLTree<K, V>, Pair<K, V>> removeFirst(); @Override Pair<AVLTree<K, V>, Pair<K, V>> removeLast(); @Override AVLTree<K, V> left(); @Override AVLTree<K, V> left(TreeMap<K, V> newLeft); @Override AVLTree<K, V> right(); @Override AVLTree<K, V> right(TreeMap<K, V> newRight); @Override AVLTree<K, V> rotateLeft(); @Override AVLTree<K, V> rotateRight(); enum constructors implements TreeFactory { factory; @Override public <K, V> AVLTree<K, V> create(Comparator<K> comparator) { return new Empty<K, V>(comparator); } @Override public <K, V> AVLTree<K, V> create(Comparator<K> comparator, K key, V value) { return create(comparator, key, value, this.<K, V>create(comparator), this.<K, V>create(comparator)); } @Override public <K, V> AVLTree<K, V> create(Comparator<K> comparator, K key, V value, TreeMap<K, V> left, TreeMap<K, V> right) { return methods.balance(new Node<K, V>(comparator, key, value, Unchecked.<AVLTree<K, V>>cast(left), Unchecked.<AVLTree<K, V>>cast(right))); } public static <K extends Comparable<? super K>, V> AVLTree<K, V> avlTree(K key, V value) { return factory.create(Comparators.<K>ascending(), key, value); } public static <K,V> TreeMapFactory<K,V, AVLTree<K,V>> factory(Comparator<K> comparator) { return TreeMapFactory.treeMapFactory(factory, comparator); } public static <K extends Comparable<? super K>,V> TreeMapFactory<K,V, AVLTree<K,V>> factory() { return TreeMapFactory.<K,V, AVLTree<K,V>>treeMapFactory(factory); } } class methods { // http://upload.wikimedia.org/wikipedia/commons/thumb/f/f5/AVL_Tree_Rebalancing.svg/350px-AVL_Tree_Rebalancing.svg.png static <K, V> AVLTree<K, V> balance(AVLTree<K, V> node) { int balance = node.balance(); if (balance == -2) return balanceRight(node); if (balance == 2) return balanceLeft(node); return node; } static <K, V> AVLTree<K, V> balanceLeft(AVLTree<K, V> node) { int balance = node.left().balance(); if (balance == -1) return balanceLeftRight(node); if (balance == 1) return balanceLeftLeft(node); return node; } static <K, V> AVLTree<K, V> balanceRight(AVLTree<K, V> node) { int balance = node.right().balance(); if (balance == 1) return balanceRightLeft(node); if (balance == -1) return balanceRightRight(node); return node; } static <K, V> AVLTree<K, V> balanceLeftLeft(AVLTree<K, V> parent) { return parent.rotateRight(); } static <K, V> AVLTree<K, V> balanceLeftRight(AVLTree<K, V> parent) { AVLTree<K, V> four = parent.left().rotateLeft(); return balanceLeftLeft(parent.left(four)); } static <K, V> AVLTree<K, V> balanceRightRight(AVLTree<K, V> parent) { return parent.rotateLeft(); } static <K, V> AVLTree<K, V> balanceRightLeft(AVLTree<K, V> parent) { AVLTree<K, V> four = parent.right().rotateRight(); return balanceRightRight(parent.right(four)); } } final class Empty<K, V> extends AbstractEmptyTreeMap<K, V, AVLTree<K, V>> implements AVLTree<K, V> { public Empty(Comparator<K> comparator) { super(comparator, AVLTree.constructors.factory); } @Override public int height() { return 0; } @Override public int balance() { return 0; } } final class Node<K, V> extends AbstractTreeMap<K, V, AVLTree<K, V>> implements AVLTree<K, V> { private final int height; private final int balance; private Node(Comparator<K> comparator, K key, V value, AVLTree<K, V> left, AVLTree<K, V> right) { super(comparator, key, value, left, right, AVLTree.constructors.factory); height = Math.max(left.height(), right.height()) + 1; balance = left.height() - right.height(); } @Override public int height() { return height; } @Override public int balance() { return balance; } } }