Data Structure - Binary Search Tree (Java)
阿新 • • 發佈:2018-12-29
package chimomo.learning.java.datastructure; /** * Implements an unbalanced binary search tree. * Note that all "matching" is based on the compareTo method. * * @author Created by Chimomo */ public class BinarySearchTree<T extends Comparable<? super T>> { /** * The tree root. */ private BinaryNode<T> root; /** * Construct the tree. */ public BinarySearchTree() { root = null; } // Test program public static void main(String[] args) throws Exception { // Create binary search tree. BinarySearchTree<Integer> t = new BinarySearchTree<>(); final int NUMS = 4000; final int GAP = 37; // Insert. for (int i = GAP; i != 0; i = (i + GAP) % NUMS) { t.insert(i); } // Get height. System.out.println("Height: " + t.height(t.root)); // Remove. for (int i = 1; i < NUMS; i += 2) { t.remove(i); } System.out.println("Checking... (no more output means success)"); // Print tree. if (NUMS < 40) { t.printTree(); } // Find min and find max. if (t.findMin() != 2 || t.findMax() != NUMS - 2) { System.out.println("FindMin or FindMax error!"); } // Contains. 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!"); } } } /** * 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 The smallest item or null if empty. */ public T findMin() throws Exception { if (isEmpty()) { throw new Exception("Binary search tree is empty!"); } return findMin(root).element; } /** * Find the largest item in the tree. * * @return The largest item of null if empty. */ public T findMax() throws Exception { if (isEmpty()) { throw new Exception("Binary search tree is empty!"); } return findMax(root).element; } /** * Find an item in the tree. * * @param x The item to search for. * @return True if found, false otherwise. */ 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 binary search 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); } else { // Duplicate; do nothing. } 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) { // Item not found; do nothing. if (t == null) { return null; } 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 The 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 The 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 The item to search for. * @param t The node that roots the subtree. * @return True if contains, false otherwise. */ 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 <AnyType> Any type */ private static class BinaryNode<AnyType> { AnyType element; // The data in the node BinaryNode<AnyType> left; // Left child BinaryNode<AnyType> right; // Right child // Constructors BinaryNode(AnyType theElement) { this(theElement, null, null); } BinaryNode(AnyType theElement, BinaryNode<AnyType> left, BinaryNode<AnyType> right) { element = theElement; this.left = left; this.right = right; } } } /* Output: Height: 119 Checking... (no more output means success) */