//<PLAINTEXT>
package Trees;

import java.util.*;

/**
 * BSTree.java
 *
 *
 * Created: Fri Apr  4 14:18:59 2003
 *
 * @author <a href="mailto:shapiro@cse.buffalo.edu">Stuart C. Shapiro</a>
 */

public class BSTree extends BinaryTree {

    /**
     * Creates a new, empty <code>BSTree</code>.
     *
     */
    public BSTree () {
	super();
    }

    /**
     * Unsupported.
     *
     * @param value the <code>Comparable</code> value to be the
     * contents of the root of this <code>BSTree</code>.
     * @param lt the left sub-<code>BSTree</code>.
     * @param rt a ritht sub-<code>BSTree</code>.
     * @exception UnsupportedOperationException
     */
    public BSTree (Comparable value, BSTree lt, BSTree rt) {
	throw new UnsupportedOperationException();
    }

    /**
     * Unsupported.
     *
     * @param value a <code>Comparable</code> value
     * @return a <code>BSTree</code> value
     * @exception UnsupportedOperationException
     */
    public static BSTree newLeaf(Comparable value) {
	throw new UnsupportedOperationException();
    }

    /**
     * Inserts a new value in sorted position in this <code>BSTree</code>.
     *
     * @param v the <code>Comparable</code> value to be inserted.
     */
    public void insert (Comparable v) {
	if (isEmpty()) {
	    setContents(v);
	    setLeft(new BSTree());
	    setRight(new BSTree());
	} else {
	    if (((Comparable)getContents()).compareTo(v) > 0) {
		((BSTree)getLeft()).insert(v);
	    } else {
		if (((Comparable)getContents()).compareTo(v) < 0) {
		    ((BSTree)getRight()).insert(v);
		} else {
		    throw
			new UnsupportedOperationException("Attempt to insert duplicate value.");
		}
	    }
	}
    }

    /**
     * Determines if a value is in this <code>BSTree</code>.
     *
     * @param v the <code>Comparable</code> value to be searched for.
     * @return  <code>true</code> if v is in this <code>BSTree</code>;
     * <code>false</code> otherwise.
     */
    public boolean contains(Comparable v) {
	return !isEmpty()
	    && (((Comparable)getContents()).compareTo(v) == 0
		|| (((Comparable)getContents()).compareTo(v) > 0
		    && ((BSTree)getLeft()).contains(v))
		|| ((BSTree)getRight()).contains(v));
    }

    /**
     * Returns the first (least) value stored in this <code>BSTree</code>.
     *
     * @return the first (least) value stored in this <code>BSTree</code>.
     */
    public Comparable getFirst() {
	if (isEmpty()) {throw new NoSuchElementException();}
	if (getLeft().isEmpty()) return (Comparable)getContents();
	else return ((BSTree)getLeft()).getFirst();
    }

    /**
     * Removes a value from this <code>BSTree</code>.
     *
     * @param v the <code>Comparable</code> value to be removed.
     */
    public void remove(Comparable v) {
	if (!isEmpty()) {
	    if (((Comparable)getContents()).compareTo(v) == 0)
		removeRoot();
	    else if (((Comparable)getContents()).compareTo(v) > 0) 
		((BSTree)getLeft()).remove(v);
	    else ((BSTree)getRight()).remove(v);
	}
    }

    /**
     * Removes the value stored in the root of this <code>BSTree</code>.
     *
     */
    public void removeRoot() {
	if (isLeaf()) {
	    makeEmpty();
	} else {
	    if (getRight().isEmpty()) {
		BSTree oldLeft = (BSTree)getLeft();
		setContents(oldLeft.getContents());
		setLeft(oldLeft.getLeft());
		setRight(oldLeft.getRight());
	    } else {
		Comparable v = (Comparable)((BSTree)getRight()).getFirst();
		setContents(v);
		((BSTree)getRight()).remove(v);
	    } // end of else
	}
    }

    /**
     * Returns an example <code>BSTree</code>.
     *
     * @return an example <code>BSTree</code>.
     */
    public static BSTree testBSTree() {
	BSTree tree = new BSTree();
	tree.insert(new Integer(15));
	tree.insert(new Integer(6)); 
	tree.insert(new Integer(18)); 
	tree.insert(new Integer(21)); 
	tree.insert(new Integer(3)); 
	tree.insert(new Integer(12)); 
	tree.insert(new Integer(16)); 
	tree.insert(new Integer(9)); 
	tree.insert(new Integer(11)); 
	tree.insert(new Integer(17)); 
	return tree;
    }

    /**
     * Tests the <code>BSTree</code> class.
     *
     * @param args a <code>String[]</code> value
     */
    public static void main (String[] args) {
	BSTree tree;
	tree = testBSTree();
	System.out.println("Example tree: " + tree);

	System.out.println(tree.contains(new Integer(9)));
	System.out.println(tree.contains(new Integer(20)));

	tree.remove(new Integer(3));
	System.out.println("After removal of 3: " + tree);

	tree = testBSTree();
	tree.remove(new Integer(12));
	System.out.println("After removal of 12: " + tree);

	tree = testBSTree();
	tree.remove(new Integer(15));
	System.out.println("After removal of 15: " + tree);
    } // end of main ()
    
    
}// BSTree
