import java.util.LinkedList;
import java.util.Queue;
/**
* Created by kiyan on 5/26/16.
*/
public class BST<Key extends Comparable<Key>, Value> {
private Node root;
public Value get(Key key) {
Node x = root;
while (x != null) {
int cmp = key.compareTo(x.key);
if (cmp < 0) {
x = x.left;
} else if (cmp > 0) {
x = x.right;
} else {
return x.val;
}
}
return null;
}
public void put(Key key, Value val) {
root = put(root, key, val);
}
private Node put(Node x, Key key, Value val) {
if (x == null) {
return new Node(key, val);
}
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.count = 1 + size(x.left) + size(x.right);
return x;
}
public Key floor(Key key) {
Node x = floor(root, key);
if (x == null) {
return null;
}
return x.key;
}
private Node floor(Node x, Key key) {
if (x == null) {
return null;
}
int cmp = key.compareTo(x.key);
if (cmp == 0) {
return x; // found
}
if (cmp < 0) {
return floor(x.left, key); // in left subtree
}
Node t = floor(x.right, key); // in right subtree
if (t != null) {
return t; // found in right
}
return x;
}
public int size() {
return size(root);
}
private int size(Node x) {
if (x == null) {
return 0;
}
return x.count;
}
public int rank(Key key) {
return rank(root, key);
}
private int rank(Node x, Key key) {
if (x == null) {
return 0;
}
int cmp = key.compareTo(x.key);
if (cmp < 0) {
return rank(x.left, key);
} else if (cmp > 0) {
return 1 + size(x.left) + rank(x.right, key); // current node + nodes in left subtree + right
} else {
return size(x.left);
}
}
public Iterable<Key> keys() {
Queue<Key> q = new LinkedList<>();
inorder(root, q);
return q;
}
private void inorder(Node x, Queue<Key> q) {
if (x == null) {
return;
}
inorder(x.left, q);
q.offer(x.key);
inorder(x.right, q);
}
public void deleteMin() {
root = deleteMin(root);
}
private Node deleteMin(Node x) {
if (x.left == null) {
return x.right;
}
x.left = deleteMin(x.left);
x.count = 1 + size(x.left) + size(x.right);
return x;
}
public void delete(Key key) {
root = delete(root, key);
}
/**
* Hibbard deletion
*/
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.count = 1 + size(x.left) + size(x.right);
return x;
}
public Node min() {
return min(root);
}
private Node min(Node x) {
if (x == null || x.left == null) {
return x;
}
return min(x.left);
}
class Node {
private Key key;
private Value val;
private Node left;
private Node right;
private int count;
public Node(Key key, Value val) {
this.key = key;
this.val = val;
}
}
}