package avltree;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class AVLTree<T extends Comparable<T>, E> implements
Iterable<AVLTreeNode<T, E>>, Map<T, E> {
private AVLTreeNode<T, E> root;
public AVLTree() {
}
public AVLTreeNode<T, E> getRoot() {
return root;
}
private volatile int size = 0;
@Override
public int size() {
return size;
}
@Override
public boolean isEmpty() {
return root == null;
}
@Override
public boolean containsKey(Object key) {
return getTreeNode(key) != null;
}
@Override
public boolean containsValue(Object value) {
throw new UnsupportedOperationException(
"Method containsValue() is not supported in this implementation.");
}
@Override
public void putAll(Map<? extends T, ? extends E> m) {
throw new UnsupportedOperationException(
"Method putAll() is not supported in this implementation.");
}
@Override
public void clear() {
throw new UnsupportedOperationException(
"Method clear() is not supported in this implementation.");
}
@Override
public Set<T> keySet() {
throw new UnsupportedOperationException(
"Method keySet() is not supported in this implementation.");
}
@Override
public Collection<E> values() {
throw new UnsupportedOperationException(
"Method values() is not supported in this implementation.");
}
@Override
public Set<java.util.Map.Entry<T, E>> entrySet() {
throw new UnsupportedOperationException(
"Method entrySet() is not supported in this implementation.");
}
public E put(T key, E value) {
AVLTreeNode<T, E> newNode = new AVLTreeNode<T, E>(key, value);
if (root == null) {
root = newNode;
return value;
}
AVLTreeNode<T, E> parent = root;
while (true) {
if (parent.compareTo(key) == 0) {
E oldValue = parent.value;
parent.value = value;
return oldValue;
}
if (parent.compareTo(key) > 0) {
// parent is bigger, put it on left side
if (parent.left == null) {
parent.left = newNode;
newNode.parent = parent;
break;
} else {
parent = parent.left;
}
} else {
// parent is smaller, put it on right side
if (parent.right == null) {
parent.right = newNode;
newNode.parent = parent;
break;
} else {
parent = parent.right;
}
}
}
AVLTreeNode.recountHight(newNode);
rotate(parent);
return null;
}
private void rotate(AVLTreeNode<T, E> currNode) {
boolean rorated = false;
while (currNode != null) {
int hDiff = currNode.getHightDiff();
if (hDiff < 2) {
if (rorated == true) {
return;
}
currNode = currNode.parent;
continue;
}
AVLTreeNode<T, E> p1 = currNode;
AVLTreeNode<T, E> p2 = null;
AVLTreeNode<T, E> p3 = null;
// tree height diff is bigger than 1, need rotate
boolean p1LeftHigher = p1.isLeftHigher();
if (p1LeftHigher == true) {
p2 = p1.left;
} else {
p2 = p1.right;
}
boolean p2LeftHigher = p2.isLeftHigher();
if (p2LeftHigher == true) {
p3 = p2.left;
} else {
p3 = p2.right;
}
if (p1LeftHigher == true && p2LeftHigher == true) {
// right rotation of p2
rotateRight(p2);
if (p2.getHightDiff() < 2) {
currNode = p2.parent;
} else {
currNode = p2;
}
} else if (p1LeftHigher == false && p2LeftHigher == false) {
// left rotation of p2
rotateLeft(p2);
if (p2.getHightDiff() < 2) {
currNode = p2.parent;
} else {
currNode = p2;
}
} else if (p1LeftHigher == true && p2LeftHigher == false) {
// left rotation of p3, then right rotation of new p3
rotateLeft(p3);
rotateRight(p3);
if (p3.getHightDiff() < 2) {
currNode = p3.parent;
} else {
currNode = p3;
}
} else if (p1LeftHigher == false && p2LeftHigher == true) {
// right rotation of p3, then left rotation of new p3
rotateRight(p3);
rotateLeft(p3);
if (p3.getHightDiff() < 2) {
currNode = p3.parent;
} else {
currNode = p3;
}
}
rorated = true;
}
}
private void rotateRight(AVLTreeNode<T, E> base) {
AVLTreeNode<T, E> bP1 = base.parent;
AVLTreeNode<T, E> bP2 = bP1.parent;
AVLTreeNode<T, E> bRgiht = base.right;
// base right point to base parent
base.right = bP1;
bP1.parent = base;
// base parent left point to base right
bP1.left = bRgiht;
if (bRgiht != null) {
bRgiht.parent = bP1;
}
// base parent point to base parent parent
base.parent = bP2;
// base parent parent left/right point to base
if (bP2 == null) {
// base parent parent is root;
root = base;
} else {
if (bP2.left == bP1) {
bP2.left = base;
} else {
bP2.right = base;
}
}
AVLTreeNode.recountHight(bP1);
}
private void rotateLeft(AVLTreeNode<T, E> base) {
AVLTreeNode<T, E> bP1 = base.parent;
AVLTreeNode<T, E> bP2 = bP1.parent;
AVLTreeNode<T, E> bLeft = base.left;
// base left point to base parent
base.left = bP1;
bP1.parent = base;
// base parent right point to base left
bP1.right = bLeft;
if (bLeft != null) {
bLeft.parent = bP1;
}
// base parent point to base parent parent
base.parent = bP2;
// base parent parent left/right point to base
if (bP2 == null) {
root = base;
} else {
if (bP1 == bP2.left) {
bP2.left = base;
} else {
bP2.right = base;
}
}
AVLTreeNode.recountHight(bP1);
}
private E deleteLeaf(AVLTreeNode<T, E> del) {
AVLTreeNode<T, E> p = del.parent;
E ret = del.value;
if (p == null) {
root = null;
} else {
if (p.left == del) {
p.left = null;
} else {
p.right = null;
}
AVLTreeNode.recountHight(p);
rotate(p);
}
del.left = null;
del.right = null;
del.parent = null;
del.key = null;
del.value = null;
return ret;
}
public E remove(Object key) {
final AVLTreeNode<T, E> del = getTreeNode(key);
if (del == null) {
return null;
}
E ret = del.value;
// leaf node, delete it, count height, rotate.
if (del.left == null && del.right == null) {
return deleteLeaf(del);
}
AVLTreeNode<T, E> delHC = del;
if (del.left != null && del.right != null) {
delHC = successor(del);
// assign delHC value to del, as if del is replaced by delHC. then
// delete delHC.
del.value = delHC.value;
del.key = delHC.key;
}
AVLTreeNode<T, E> dr = delHC.right;
AVLTreeNode<T, E> dl = delHC.left;
AVLTreeNode<T, E> p = delHC.parent;
if (dr == null && dl == null) {
return deleteLeaf(del);
}
if (dl == null) {
// have right child
dr.parent = p;
if (p != null) {
if (p.left == delHC) {
p.left = dr;
} else {
p.right = dr;
}
AVLTreeNode.recountHight(p);
rotate(p);
} else {
root = dr;
AVLTreeNode.recountHight(dr);
rotate(dr);
}
} else if (dr == null) {
// have left child
dl.parent = p;
if (p != null) {
if (p.left == delHC) {
p.left = dl;
} else {
p.right = dl;
}
AVLTreeNode.recountHight(p);
rotate(p);
} else {
root = dl;
AVLTreeNode.recountHight(dl);
rotate(dl);
}
}
delHC.key = null;
delHC.value = null;
delHC.left = null;
delHC.right = null;
delHC.parent = null;
return ret;
}
public E get(Object key) {
AVLTreeNode<T, E> valueNode = getTreeNode(key);
if (valueNode == null) {
return null;
} else {
return valueNode.value;
}
}
public AVLTreeNode<T, E> getTreeNode(Object key) {
if (key == null) {
return null;
}
AVLTreeNode<T, E> currNode = root;
while (currNode != null) {
int cmp = currNode.compareTo(key);
if (cmp == 0) {
return currNode;
}
if (cmp > 0) {
currNode = currNode.left;
} else {
currNode = currNode.right;
}
}
return null;
}
public void preoderTraversal(AVLTreeNode<T, E> node,
ITraverseAVLTree<T, E> handler) {
handler.traverse(node);
if (node.left != null) {
preoderTraversal(node.left, handler);
}
if (node.right != null) {
preoderTraversal(node.right, handler);
}
}
public void inoderTraversal(AVLTreeNode<T, E> node,
ITraverseAVLTree<T, E> handler) {
if (node.left != null) {
inoderTraversal(node.left, handler);
}
handler.traverse(node);
if (node.right != null) {
inoderTraversal(node.right, handler);
}
}
public void postoderTraversal(AVLTreeNode<T, E> node,
ITraverseAVLTree<T, E> handler) {
if (node.left != null) {
postoderTraversal(node.left, handler);
}
if (node.right != null) {
postoderTraversal(node.right, handler);
}
handler.traverse(node);
}
public Iterator<AVLTreeNode<T, E>> iterator() {
return new AVLTreeIterator();
}
public AVLTreeNode<T, E> successor(AVLTreeNode<T, E> node) {
if (node.right != null) {
AVLTreeNode<T, E> s = node.right;
while (s.left != null) {
s = s.left;
}
return s;
}
AVLTreeNode<T, E> p = node.parent;
AVLTreeNode<T, E> s = node;
while (p != null && p.right == s) {
s = p;
p = s.parent;
}
return p;
}
class AVLTreeIterator implements Iterator<AVLTreeNode<T, E>> {
private AVLTreeNode<T, E> current = null;
public AVLTreeIterator() {
if (root == null) {
current = null;
return;
}
AVLTreeNode<T, E> tmp = root;
while (tmp.left != null) {
tmp = tmp.left;
}
current = tmp;
}
@Override
public boolean hasNext() {
return current != null;
}
@Override
public AVLTreeNode<T, E> next() {
AVLTreeNode<T, E> ret = current;
current = successor(current);
return ret;
}
@Override
public void remove() {
AVLTree.this.remove(current.key);
}
}
}