public class Node
{
private int data;
private Node left;
private Node right;
private Node parent;
public Node()
{
data = 0;
left = null;
right = null;
parent = null;
}
public Node(int e)
{
data = e;
left = null;
right = null;
parent = null;
}
public int getData()
{
return data;
}
public Node getLeft()
{
return left;
}
public Node getRight()
{
return right;
}
public Node getParent()
{
return parent;
}
public void setData(int d)
{
data = d;
}
public void setLeft(Node l)
{
left = l;
}
public void setRight(Node r)
{
right = r;
}
public void setParent(Node p)
{
parent = p;
}
}
public class BST
{
private Node root;
/** Initialize a tree
*/
public BST()
{
root = null;
}
/** Return the root of the tree
* @return {@code Node}, root of tree
*/
// O(1)
public Node getRoot()
{
return root;
}
/** Set a node for root
* @param Node, node
* @return none
*/
// O(1)
public void setRoot(Node n)
{
root = n;
}
/** Check if the tree is an empty tree
* @return {@code bool}, tree if tree is empty; false otherwise
*/
// O(1)
public boolean isEmpty()
{
return (root == null);
}
/** Get the size of the tree
* @return {@code int}, number of elements in tree
*/
// O(n)
public int size()
{
return getSize(root);
}
public int getSize(Node n)
{
if(n == null) return 0;
return 1+getSize(n.getLeft())+getSize(n.getRight());
}
/** Check if two trees are same
* @param BST a binary search tree
* @return {@code bool}, tree if two trees are same; false otherwise
*/
// O(n)
public boolean equals(BST t)
{
if(size() != t.size()) return false;
return nodeEquals(root, t.root);
}
public boolean nodeEquals(Node n1, Node n2)
{
if(n1 == null && n2 == null) return true;
if(n1 == null && n2 != null) return false;
if(n1 != null & n2 == null) return false;
if(n1.getData() != n2.getData()) return false;
return nodeEquals(n1.getLeft(), n2.getLeft()) && nodeEquals(n1.getRight(), n2.getRight());
}
/** Print elements in ascending ord
*/
// O(n)
public void inorderWalk()
{
if(root != null) printLDR(root);
System.out.println();
}
public void printLDR(Node n)
{
if(n == null) return;
printLDR(n.getLeft());
System.out.printf("%5d", n.getData());
printLDR(n.getRight());
}
/** Print element in pre-order
*/
// O(n)
public void preorderWalk()
{
if(root != null) printDLR(root);
System.out.println();
}
public void printDLR(Node n)
{
if(n == null) return;
System.out.printf("%5d", n.getData());
printDLR(n.getLeft());
printDLR(n.getRight());
}
/** Print elements in post-order
*/
// O(n)
public void postorderWalk()
{
if(root != null) printLRD(root);
System.out.println();
}
public void printLRD(Node n)
{
if(n == null) return;
printLRD(n.getLeft());
printLRD(n.getRight());
System.out.printf("%5d", n.getData());
}
/** Insert an element into the tree with the algorithm in CLRS
* @param, int value of inserting element
*/
// O(lgn)
public void insert(int e)
{
if(search(e)) return;
Node parent = null;
Node current = root;
while(current != null)
{
parent = current;
current = (e < current.getData())?parent.getLeft():parent.getRight();
}
Node temp = new Node(e);
temp.setParent(parent);
if(parent == null)
root = temp;
else
{
if (e < parent.getData())
parent.setLeft(temp);
else
parent.setRight(temp);
}
}
/** Replace a subtree with other subtree
* @param u target subtree
* @param v replace subtree
*/
// O(1)
public void transplant(Node u, Node v)
{
if(u.getParent() == null)
root = v;
else if(u == u.getParent().getLeft())
u.getParent().setLeft(v);
else
u.getParent().setRight(v);
if(v != null)
v.setParent(u.getParent());
}
/** Delete an element in tree
* @param int value of an element
*/
// O(lgn)
public void delete(int e)
{
if(!search(e)) return;
Node z = searchNode(root, e);
//z has no child or only one child
if(z.getLeft() == null)
transplant(z, z.getRight());
else if(z.getRight() == null)
transplant(z, z.getLeft());
//z has two children
else
{
Node y = getMin(z.getRight());
if(y.getParent() != z)//y is not z's child
{
transplant(y, y.getRight());
y.setRight(z.getRight());
y.getRight().setParent(y);
}
transplant(z, y);
y.setLeft(z.getLeft());
y.getLeft().setParent(y);
}
}
/** Get the successor of an element in tree
* @param int value of the element
* @return {@code int}, value of successor
*/
// O(lgn)
public int successor(int e)
{
Node n = getSuccessor(root, e);
if (n == null) return -1;
return n.getData();
}
public Node getSuccessor(Node n, int e)
{
if(!search(e))
return null;
Node target = searchNode(n, e);
//if the right subtree of node is nonempty
if(target.getRight() != null)
return getMin(target.getRight());
Node p = target.getParent();
//if node is leave, the right subtree is empty
while (p != null && target == p.getRight()) {
target = p;
p = p.getParent();
}
return p;
}
/** Get the predecessor of an element in tree
* @param int value of the element
* @return {@code int}, value of predecessor
*/
// O(lgn)
public int predecessor(int e)
{
Node n = getPredecessor(root, e);
if (n == null) return -1;
return n.getData();
}
public Node getPredecessor(Node n, int e)
{
if(!search(e))
return null;
Node target = searchNode(n, e);
//if the left subtree of node is nonempty
if(target.getLeft() != null)
return getMax(target.getLeft());
Node p = target.getParent();
//if node is leave, the left subtree is empty
while(p != null && target == p.getLeft()){
target = p;
p = p.getParent();
}
return p;
}
/** Get the height of the tree
*/
// O(lgn)
public int height()
{
return getHeight(root);
}
public int getHeight(Node n)
{
if(n == null) return 0;
if(n.getLeft() == null && n.getRight() == null)
return 1;
int l = getHeight(n.getLeft());
int r = getHeight(n.getRight());
return (l>r)?(1+l):(1+r);
}
/** Search an element in tree
* @param int, the value of an element
* @return {@code boolean}, true if the tree contains the element and false otherwise
*/
// O(lgn)
public boolean search(int e)
{
return searchNode(root, e) != null;
}
public Node searchNode(Node n, int e)
{
if(n == null) return null;
if(n.getData() == e) return n;
if(e < n.getData())
return searchNode(n.getLeft(), e);
else
return searchNode(n.getRight(), e);
}
/** Get the minimum element in tree
* @param none
* @return {@code int}, value of the minimum element in tree
*/
// O(lgn)
public int min()
{
Node n = getMin(root);
return n.getData();
}
public Node getMin(Node n)
{
if(n.getLeft() == null)
return n;
return getMin(n.getLeft());
}
/** Get the maximum element in tree
* @param none
* @return int, value of the maximum element in tree
*/
// O(lgn)
public int max()
{
Node n = getMax(root);
return n.getData();
}
public Node getMax(Node n)
{
if(n.getRight() == null)
return n;
return getMax(n.getRight());
}
}
public class BSTTest
{
public static void main(String args[])
{
BST t = new BST();
// Create tree
t.insert(8);
t.insert(3);
t.insert(10);
t.insert(1);
t.insert(6);
t.insert(14);
t.insert(4);
t.insert(7);
t.insert(13);
t.insert(15);
// Display tree
t.inorderWalk();
// Search
System.out.println(t.search(7));//true
System.out.println(t.search(20));//false
// Min
System.out.println("Min: "+t.min());//1
// Max
System.out.println("Max: "+t.max());//15
// Height
System.out.println("Height: "+t.height());//4
// Successor
System.out.println("Successor: "+t.successor(3));//4
System.out.println("Successor: "+t.successor(7));//8
System.out.println("Successor: "+t.successor(8));//10
System.out.println("Successor: "+t.successor(15));//-1
// Predecessor
System.out.println("Predecessor: "+t.predecessor(13));//10
System.out.println("Predecessor: "+t.predecessor(10));//8
System.out.println("Predecessor: "+t.predecessor(8));//7
System.out.println("Predecessor: "+t.predecessor(1));//-1
//delete
t.delete(3);
t.inorderWalk();
}
}