更新说明
在二叉搜索树V1.0的编程实现中,我们实现了BST的查找、插入,左右儿子删除的功能,但写的确实很一般,这里就Update一下。
功能介绍
- void insert(x) → Insert x
- void remove(x) → Remove x
- boolean contains(x) → Return true if x is present
- Comparable findMin() → Return smallest item
- Comparable findMax() → Return largest item
- boolean isEmpty() → Return true if empty; else false
- void makeEmpty() → Remove all items
- void printTree() → Print tree in sorted order
异常类
当集合容器为空的时候就不能够删除或获取元素,这时就会出现一种异常,命名为UnderflowException:
/**
* Exception class for access in empty containers
* such as stacks, queues, and priority queues.
*/
public class UnderflowException extends RuntimeException {}
编程实现
/**
* Implements an unbalanced binary search tree.
* Note that all "matching" is based on the compareTo method.
*/
public class BinarySearchTree<T extends Comparable<? super T>> {
/**
* The tree root.
*/
private BinaryNode<T> root;
/**
* Construct the tree.
*/
public BinarySearchTree() {
root = null;
}
/**
* Insert into the tree; duplicates are ignored.
* @param x the item to insert.
*/
public void insert(T x) {
root = insert(x, root);
}
/**
* Remove from the tree. Nothing is done if x is not found.
* @param x the item to remove.
*/
public void remove(T x) {
root = remove(x, root);
}
/**
* Find the smallest item in the tree.
* @return smallest item or null if empty.
*/
public T findMin() {
if(isEmpty()) {
throw new UnderflowException( );
}
return findMin(root).element;
}
/**
* Find the largest item in the tree.
* @return the largest item of null if empty.
*/
public T findMax( )
{
if( isEmpty( ) )
throw new UnderflowException( );
return findMax( root ).element;
}
/**
* Find an item in the tree.
* @param x the item to search for.
* @return true if not found.
*/
public boolean contains(T x) {
return contains(x, root);
}
/**
* Make the tree logically empty.
*/
public void makeEmpty() {
root = null;
}
/**
* Test if the tree is logically empty.
* @return true if empty, false otherwise.
*/
public boolean isEmpty() {
return root == null;
}
/**
* Print the tree contents in sorted order.
*/
public void printTree() {
if(isEmpty()) {
System.out.println("Empty tree");
} else {
printTree(root);
}
}
/**
* Internal method to insert into a subtree.
* @param x the item to insert.
* @param t the node that roots the subtree.
* @return the new root of the subtree.
*/
private BinaryNode<T> insert(T x, BinaryNode<T> t) {
if(t == null) {
return new BinaryNode<>( x, null, null );
}
int compareResult = x.compareTo(t.element);
if(compareResult < 0) {
t.left = insert( x, t.left);
} else if(compareResult > 0) {
t.right = insert(x, t.right);
}
return t;
}
/**
* Internal method to remove from a subtree.
* @param x the item to remove.
* @param t the node that roots the subtree.
* @return the new root of the subtree.
*/
private BinaryNode<T> remove(T x, BinaryNode<T> t) {
if(t == null) {
return null; // Item not found; do nothing
}
int compareResult = x.compareTo(t.element);
if(compareResult < 0) {
t.left = remove(x, t.left);
} else if(compareResult > 0) {
t.right = remove(x, t.right);
} else if(t.left != null && t.right != null) { // Two children
t.element = findMin(t.right).element;
t.right = remove(t.element, t.right);
} else {
t = (t.left != null) ? t.left : t.right;
}
return t;
}
/**
* Internal method to find the smallest item in a subtree.
* @param t the node that roots the subtree.
* @return node containing the smallest item.
*/
private BinaryNode<T> findMin(BinaryNode<T> t) {
if(t == null) {
return null;
} else if(t.left == null) {
return t;
}
return findMin(t.left);
}
/**
* Internal method to find the largest item in a subtree.
* @param t the node that roots the subtree.
* @return node containing the largest item.
*/
private BinaryNode<T> findMax(BinaryNode<T> t) {
if(t != null) {
while(t.right != null) {
t = t.right;
}
}
return t;
}
/**
* Internal method to find an item in a subtree.
* @param x is item to search for.
* @param t the node that roots the subtree.
* @return node containing the matched item.
*/
private boolean contains(T x, BinaryNode<T> t) {
if(t == null) {
return false;
}
int compareResult = x.compareTo(t.element);
if(compareResult < 0) {
return contains( x, t.left);
} else if(compareResult > 0) {
return contains(x, t.right);
} else {
return true; // Match
}
}
/**
* Internal method to print a subtree in sorted order.
* @param t the node that roots the subtree.
*/
private void printTree(BinaryNode<T> t) {
if(t != null) {
printTree(t.left);
System.out.println(t.element);
printTree(t.right);
}
}
/**
* Internal method to compute height of a subtree.
* @param t the node that roots the subtree.
*/
private int height(BinaryNode<T> t) {
if(t == null) {
return -1;
} else {
return 1 + Math.max(height(t.left), height(t.right));
}
}
/**
* Basic node stored in unbalanced binary search trees.
* @param <T>
*/
private static class BinaryNode<T> {
BinaryNode( T theElement ) {
this(theElement, null, null);
}
BinaryNode(T theElement, BinaryNode<T> lt, BinaryNode<T> rt) {
element = theElement;
left = lt;
right = rt;
}
T element; // The data in the node
BinaryNode<T> left; // Left child
BinaryNode<T> right; // Right child
}
}
测试
public class BinarySearchTreeTest {
public static void main(String [] args) {
BinarySearchTree<Integer> t = new BinarySearchTree<>();
final int NUMS = 4000;
final int GAP = 37;
System.out.println("Checking... (no more output means success)");
for(int i = GAP; i != 0; i = (i + GAP) % NUMS) {
t.insert(i);
}
for(int i = 1; i < NUMS; i+= 2) {
t.remove(i);
}
if(NUMS < 40) {
t.printTree();
}
if(t.findMin() != 2 || t.findMax( ) != NUMS-2) {
System.out.println("FindMin or FindMax error!");
}
for(int i = 2; i < NUMS; i+=2) {
if(!t.contains(i)) {
System.out.println("Find error1!");
}
}
for(int i = 1; i < NUMS; i+=2) {
if(t.contains(i)) {
System.out.println("Find error2!");
}
}
}
}
测试结果:
Checking... (no more output means success)