// make a right-leaning link lean to the left private Node rotateLeft(Node h) { // assert (h != null) && isRed(h.right); Node x = h.right; h.right = x.left; x.left = h; x.color = x.left.color; x.left.color = RED; x.N = h.N; h.N = size(h.left) + size(h.right) + 1; return x; }

@Override public void put(Key key, Value value) { // search for key, update value if found, grow table if new Node t = new Node(null, key, value); if (root == null) { root = t; return; } Node parent = null; Node x = root; while (x != null) { parent = x; int cmp = key.compareTo(x.key); compares++; if (cmp < 0) x = x.left; else if (cmp > 0) x = x.right; else { x.value = value; return; } } int cmp = key.compareTo(parent.key); compares++; if (cmp < 0) parent.left = t; else parent.right = t; t.parent = parent; // adjust tree sizes; while (parent != null) { parent.N += 1; parent = parent.parent; } }

private Node delete(Node x, Key key) { if (x == null) return null; int comp = key.compareTo(x.key); if (comp < 0) x.left = delete(x.left, key); else if (comp > 0) x.right = delete(x.right, key); else { if (x.left == null) { if (x.pred != null) x.pred.succ = x.succ; if (x.succ != null) x.succ.pred = x.pred; return x.right; } if (x.right == null) { if (x.pred != null) x.pred.succ = x.succ; if (x.succ != null) x.succ.pred = x.pred; return x.left; } Node t = max(x.left); t.left = deleteMaxWithOutDeleteThread(x.left); t.right = x.right; if (x.pred != null) x.pred.succ = x.succ; if (x.succ != null) x.succ.pred = x.pred; x = t; } x.N = size(x.left) + size(x.right) + 1; x.height = Math.max(height(x.left), height(x.right)) + 1; x.avgCompares = (avgCompares(x.left) * size(x.left) + avgCompares(x.right) * size(x.right) + size(x)) / size(x); return x; }

private Node put(Node x, Key key, Value val) { if (x == null) { Node pre = floor(root, key); Node nex = ceiling(root, key); lastest = new Node(key, val, 1, 1, 1); if (pre != null) pre.succ = lastest; if (nex != null) nex.pred = lastest; lastest.succ = nex; lastest.pred = pre; return lastest; } int comp = key.compareTo(x.key); if (comp < 0) x.left = put(x.left, key, val); else if (comp > 0) x.right = put(x.right, key, val); else { lastest = x; x.value = val; } x.N = size(x.right) + size(x.left) + 1; x.height = Math.max(height(x.left), height(x.right)) + 1; x.avgCompares = (avgCompares(x.left) * size(x.left) + avgCompares(x.right) * size(x.right) + size(x)) / size(x); return x; }

private Node put(Node x, Key key, Value val) { if (x == null) return new Node(key, val, 1); int cmp = key.compareTo(x.key); if (cmp < 0) x.left = put(x.left, key, val); else if (cmp > 0) x.right = put(x.right, key, val); else x.val = val; x.N = 1 + size(x.left) + size(x.right); return x; }

// restore red-black tree invariant private Node balance(Node h) { // assert (h != null); if (isRed(h.right)) h = rotateLeft(h); if (isRed(h.left) && isRed(h.left.left)) h = rotateRight(h); if (isRed(h.left) && isRed(h.right)) flipColors(h); h.N = size(h.left) + size(h.right) + 1; return h; }

private Node deleteMaxWithOutDeleteThread(Node x) { if (x == null) return null; if (x.right == null) { return x.left; } x.right = deleteMax(x.right); x.N = size(x.left) + size(x.right) + 1; x.height = Math.max(height(x.left), height(x.right)) + 1; x.avgCompares = (avgCompares(x.left) * size(x.left) + avgCompares(x.right) * size(x.right) + size(x)) / size(x); return x; }

private Node put(final Node x, final Point2D key, final boolean vertical) { if (x == null) { return new Node(key, 1); } double cmp; if (vertical) { cmp = key.x() - x.key.x(); } else { cmp = key.y() - x.key.y(); } if (key.equals(x.key)) { // do nothing } else if (cmp <= 0) { x.left = put(x.left, key, !vertical); x.N = 1 + size(x.left) + size(x.right); } else if (cmp > 0) { x.right = put(x.right, key, !vertical); x.N = 1 + size(x.left) + size(x.right); } return x; }

private Node deleteMax(Node x) { if (x == null) return null; if (x.right == null) { if (x.pred != null) x.pred.succ = x.succ; if (x.succ != null) x.succ.pred = x.pred; return x.left; } x.right = deleteMax(x.right); x.N = size(x.left) + size(x.right) + 1; x.height = Math.max(height(x.left), height(x.right)) + 1; x.avgCompares = (avgCompares(x.left) * size(x.left) + avgCompares(x.right) * size(x.right) + size(x)) / size(x); return x; }

private Node delete(Node x, Key key) { if (x == null) return null; int cmp = key.compareTo(x.key); if (cmp < 0) x.left = delete(x.left, key); else if (cmp > 0) x.right = delete(x.right, key); else { if (x.right == null) return x.left; if (x.left == null) return x.right; Node t = x; x = min(t.right); x.right = deleteMin(t.right); x.left = t.left; } x.N = size(x.left) + size(x.right) + 1; return x; }

// insert the key-value pair in the subtree rooted at h private Node put(Node h, Key key, Value val) { if (h == null) return new Node(key, val, RED, 1); int cmp = key.compareTo(h.key); if (cmp < 0) h.left = put(h.left, key, val); else if (cmp > 0) h.right = put(h.right, key, val); else h.val = val; // fix-up any right-leaning links if (isRed(h.right) && !isRed(h.left)) h = rotateLeft(h); if (isRed(h.left) && isRed(h.left.left)) h = rotateRight(h); if (isRed(h.left) && isRed(h.right)) flipColors(h); h.N = size(h.left) + size(h.right) + 1; return h; }

private Node delete(Node node, Key key) { if (node == null) return null; int cmp = key.compareTo(node.key); if (cmp < 0) node.left = delete(node.left, key); else if (cmp > 0) node.right = delete(node.right, key); else { // replace node with its successor if (node.right == null) return node.left; if (node.left == null) return node.right; Node t = node; node = min(t.right); node.right = deleteMin(t.right); node.left = t.left; } node.N = size(node.left) + size(node.right) + 1; return node; }

private Node deleteMax(Node node) { if (node.right == null) return node.left; node.right = deleteMax(node.right); node.N = size(node.left) + size(node.right) + 1; return node; }

private Node deleteMax(Node x) { if (x.right == null) return x.left; x.right = deleteMax(x.right); x.N = size(x.left) + size(x.right) + 1; return x; }

// fix auxiliary information (subtree count and max fields) private void fix(Node x) { if (x == null) return; x.N = 1 + size(x.left) + size(x.right); x.max = max3(x.interval.high, max(x.left), max(x.right)); }