public class LLRB, Value> { private static final boolean RED = true; private static final boolean BLACK = false; private Node root; private class Node { private Key key; private Value val; private Node left, right; private boolean color; // true == RED, false == BLACK Node(Key key, Value val) { this.key = key; this.val = val; this.color = RED; } public String toString() { return "["+key+","+val+"]"; } } public Value get(Key key) { Node x = root; while (x != null) { int cmp = key.compareTo(x.key); if (cmp == 0) return x.val; else if (cmp < 0) x = x.left; else if (cmp > 0) x = x.right; } return null; } /* ============================================== Main insert method ============================================== */ public void put(Key key, Value value) { root = insert(root, key, value); root.color = BLACK; } /* ============================================== HELPER insert method (recursive) h = root node of the subtree Insert (key, value) in subtree at root h Return the new tree after insertion ============================================== */ private Node insert(Node h, Key key, Value value) { if (h == null) return new Node(key, value); /* ------------------------------------- This is the BST insert alg. ------------------------------------- */ int cmp = key.compareTo(h.key); if (cmp < 0) h.left = insert(h.left, key, value); // insert (key, value) in left else if (cmp > 0) h.right = insert(h.right, key, value); // insert (key, value) in right else h.val = value; // Found, update value if (isRed(h.right) && !isRed(h.left)) // This forces Left Leaning RB h = rotateLeft(h); if (isRed(h.left) && isRed(h.left.left)) h = rotateRight(h); if (isRed(h.left) && isRed(h.right)) colorFlip(h); return h; } private Node fixUp(Node h) { /* ============================== Fix RB tree (on the way UP) ============================== */ /* ------------------------------------------------ h x / \ ===> / \ y(B) x(R) h(R*) b / \ / \ a b y(B) a ------------------------------------------------ */ if (isRed(h.right) && !isRed(h.left)) // This forces Left Leaning RB h = rotateLeft(h); /* ------------------------------------------------ h x(R) / \ ===> / \ x(R) y a(R) h(R*) / \ / \ a(R) b b y ------------------------------------------------ */ if (isRed(h.left) && isRed(h.left.left)) h = rotateRight(h); /* ------------------------------------------------ h(B) h(R) / \ ===> / \ x(R) y(R) x(B) y(B) ------------------------------------------------ */ if (isRed(h.left) && isRed(h.right)) colorFlip(h); return h; } public void delete(Key key) { root = delete(root, key); root.color = BLACK; } private Node delete(Node h, Key key) { if (key.compareTo(h.key) < 0) { if (!isRed(h.left) && !isRed(h.left.left)) h = moveRedLeft(h); h.left = delete(h.left, key); } else { if (isRed(h.left)) h = rotateRight(h); if (key.compareTo(h.key) == 0 && (h.right == null)) return null; if (!isRed(h.right) && !isRed(h.right.left)) h = moveRedRight(h); if (key.compareTo(h.key) == 0) { Node minNode = null; /* minNode = min( h.right ); // Node with min in right subtree */ h.val = minNode.val; h.key = minNode.key; h.right = deleteMin(h.right); } else h.right = delete(h.right, key); } return fixUp(h); } public void deleteMin() { root = deleteMin(root); root.color = BLACK; } private Node deleteMin(Node h) { if (h.left == null) return null; if (!isRed(h.left) && !isRed(h.left.left)) h = moveRedLeft(h); h.left = deleteMin(h.left); return fixUp(h); } /* ==================================================== Auxiliary methods ==================================================== */ Node rotateLeft(Node h) { printTree(); System.out.println("*** rotateLeft(" + h + ")"); Node x = h.right; h.right = x.left; x.left = h; x.color = h.color; h.color = RED; return x; } Node rotateRight(Node h) { printTree(); System.out.println("*** rotateRight(" + h + ")"); Node x = h.left; h.left = x.right; x.right = h; x.color = h.color; h.color = RED; return x; } void colorFlip(Node h) { printTree(); System.out.println("*** flipColor(" + h + ")"); h.color = !h.color; h.left.color = !h.left.color; h.right.color = !h.right.color; } /* ======================================= Auxiliary methods for delete ======================================= */ private Node moveRedLeft(Node h) { colorFlip(h); if (isRed(h.right.left)) { h.right = rotateRight(h.right); h = rotateLeft(h); colorFlip(h); } return h; } private Node moveRedRight(Node h) { colorFlip(h); if (isRed(h.left.left)) { h = rotateRight(h); colorFlip(h); } return h; } boolean isRed(Node x) { if ( x == null ) return false; // external nodes are black return x.color; } /* ========================== Print tree ========================== */ public void printnode(Node x, int h) { String color; color = x.color?"(R)":"(B)"; for (int i = 0; i < h; i++) System.out.print(" "); System.out.println("[" + x.key + "," + x.val + "]" + color); } void printTree() { System.out.println("================================================"); showR( root, 0 ); System.out.println("================================================"); } public void showR(Node t, int h) { if (t == null) return; showR(t.right, h+1); printnode(t, h); showR(t.left, h+1); } }