package redblacktree; import java.util.Collection; import java.util.Map; import java.util.Set; public class RBTree<T extends Comparable<T>, E> implements Map<T, E> { public static final boolean RED = true; public static final boolean BLACK = false; private RBTreeNode<T, E> root; private int size; public RBTreeNode<T, E> getRoot() { return root; } public static class RBTreeNode<T extends Comparable<T>, E> { RBTreeNode<T, E> parent; RBTreeNode<T, E> left; RBTreeNode<T, E> right; boolean color = RED; T key; E value; public RBTreeNode(T key, E value) { this.key = key; this.value = value; } public int compareTo(T another) { return key.compareTo(another); } public String toString() { String p = (parent == null) ? "NULL" : parent.key.toString(); String l = (left == null) ? "NULL" : left.key.toString(); String r = (right == null) ? "NULL" : right.key.toString(); return "node: " + key + ", p: " + p + ", left: " + l + ", right: " + r; } } @Override public int size() { return size; } @Override public boolean isEmpty() { return root == null; } @Override public boolean containsKey(Object key) { // TODO Auto-generated method stub return false; } @Override public boolean containsValue(Object value) { throw new UnsupportedOperationException( "Method containsValue() is not supported in this implementation."); } @SuppressWarnings("unchecked") @Override public E get(Object key) { T nkey = (T) key; RBTreeNode<T, E> node = getNodeByKey(nkey); if (node == null) { return null; } return node.value; } private RBTreeNode<T, E> getNodeByKey(T key) { RBTreeNode<T, E> current = root; while (current != null) { int cmp = current.compareTo(key); if (cmp > 0) { current = current.left; } else if (cmp < 0) { current = current.right; } else { return current; } } return null; } @Override public E put(T key, E value) { RBTreeNode<T, E> node = new RBTreeNode<T, E>(key, value); if (root == null) { root = node; root.color = BLACK; size++; return null; } RBTreeNode<T, E> curr = root; int cmp; while (true) { cmp = curr.compareTo(key); if (cmp == 0) { E oldValue = curr.value; curr.value = value; return oldValue; } else if (cmp < 0) { if (curr.right == null) { break; } curr = curr.right; } else { if (curr.left == null) { break; } else { curr = curr.left; } } } if (cmp < 0) { curr.right = node; } else if (cmp > 0) { curr.left = node; } node.parent = curr; adjustAfterAdd(node); root.color = BLACK; return null; } private boolean colorOf(RBTreeNode<T, E> node) { if (node == null) { return BLACK; } return node.color; } private boolean isLeft(RBTreeNode<T, E> node) { if (node == null || node.parent == null) { throw new IllegalArgumentException("Node or node parent is null"); } return node.parent.left == node; } private boolean colorOfBrother(RBTreeNode<T, E> node) { if (node == null || node.parent == null) { throw new IllegalArgumentException("Node or node parent is null"); } if (isLeft(node)) { return colorOf(node.parent.right); } else { return colorOf(node.parent.left); } } private void toRed(RBTreeNode<T, E> node) { if (node == null) { return; } node.color = RED; } private void toBlack(RBTreeNode<T, E> node) { if (node == null) { return; } node.color = BLACK; } private RBTreeNode<T, E> brotherOf(RBTreeNode<T, E> node) { if (node == null || node.parent == null) { return null; } if (isLeft(node)) { return node.parent.right; } return node.parent.left; } // private void checkCircular(RBTreeNode<?, ?> root, HashSet<Object> nodes) // { // if (root == null) { // return; // } // if (nodes == null) { // nodes = new HashSet<Object>(); // } // if (nodes.contains(root)) { // throw new RuntimeException("Circular! "); // } // nodes.add(root); // checkCircular(root.left, nodes); // checkCircular(root.right, nodes); // } // // private void printStructure(RBTreeNode<?, ?> node) { // System.out.println("node\t" + node.toString()); // System.out.println("nodeP\t" // + (node.parent == null ? "NULL" : node.parent.toString())); // System.out.println("nodeL\t" // + (node.left == null ? "NULL" : node.left.toString())); // System.out.println("nodeR\t" // + (node.right == null ? "NULL" : node.right.toString())); // System.out.println("============="); // } private void adjustAfterAdd(RBTreeNode<T, E> node) { while (node != null && colorOf(node) == RED && colorOf(node.parent) == RED) { RBTreeNode<T, E> p = node.parent; if (colorOfBrother(p) == RED) { toBlack(p); toBlack(brotherOf(p)); toRed(p.parent); node = p.parent; continue; } // now, handle this condition: parent is red, brother of parent is // black boolean l = isLeft(node); boolean pl = isLeft(p); if (l != pl) { if (l == true) { rotateRight(node); } else { rotateLeft(node); } node = p; p = node.parent; } pl = isLeft(p); RBTreeNode<T, E> pp = p.parent; if (pl == true) { rotateRight(p); toBlack(p); toRed(pp); } else { rotateLeft(p); toBlack(p); toRed(pp); } return; } } private void rotateRight(RBTreeNode<T, E> node) { RBTreeNode<T, E> p = node.parent; if (p == null || p.left != node) { throw new IllegalArgumentException("Can not rotate root node"); } RBTreeNode<T, E> pp = p.parent; p.left = node.right; if (node.right != null) { node.right.parent = p; } node.parent = pp; if (pp == null) { root = node; } else if (isLeft(p)) { pp.left = node; } else { pp.right = node; } node.right = p; p.parent = node; } private void rotateLeft(RBTreeNode<T, E> node) { RBTreeNode<T, E> p = node.parent; // if (p == null) { // throw new IllegalArgumentException("Can not rotate root node"); // } RBTreeNode<T, E> pp = p.parent; p.right = node.left; if (node.left != null) { node.left.parent = p; } node.parent = pp; if (pp == null) { root = node; } else if (isLeft(p) == true) { pp.left = node; } else { pp.right = node; } node.left = p; p.parent = node; } /** * the smallest element which is bigger than node * * @param node * @return */ private RBTreeNode<T, E> successor(RBTreeNode<T, E> node) { if (node.right == null) { return null; } node = node.right; while (node.left != null) { node = node.left; } return node; } /** * the biggest element which is smaller than node * * @param node * @return */ private RBTreeNode<T, E> previous(RBTreeNode<T, E> node) { if (node.parent == null) { return null; } RBTreeNode<T, E> p = node.parent; while (p != null) { node = node.right; } return node; } @SuppressWarnings("unchecked") @Override public E remove(Object key) { T nkey = (T) key; // references to the one to delete RBTreeNode<T, E> node = getNodeByKey(nkey); if (node == null) { return null; } if (node.left != null && node.right != null) { RBTreeNode<T, E> s = successor(node); node.value = s.value; node.key = s.key; node = s; } RBTreeNode<T, E> replace = null; if (node.left != null) { replace = node.left; } else if (node.right != null) { replace = node.right; } if (replace != null) { // node to delete is not leaf node replace.parent = node.parent; if (node.parent == null) { root = replace; } else if (isLeft(node) == true) { node.parent.left = replace; } else { node.parent.right = replace; } node.parent = node.left = node.right = null; if (node.color == BLACK) { adjustAfterDeletion(replace); } } else if (node == root) { // root is the only node and it will be deleted root = null; } else { if (node.color == BLACK) { adjustAfterDeletion(node); } // node to delete is leaf node; if (isLeft(node) == true) { node.parent.left = null; } else { node.parent.right = null; } node.parent = node.left = node.right = null; } return null; } private void adjustAfterDeletion(RBTreeNode<T, E> node) { } @Override public void putAll(Map<? extends T, ? extends E> m) { // TODO Auto-generated method stub } @Override public void clear() { // TODO Auto-generated method stub } @Override public Set<T> keySet() { // TODO Auto-generated method stub return null; } @Override public Collection<E> values() { // TODO Auto-generated method stub return null; } @Override public Set<java.util.Map.Entry<T, E>> entrySet() { // TODO Auto-generated method stub return null; } }