二叉查找树 Java实现

二叉查找树是一棵二叉树,特别之处在于:对于树中的每个节点X,它的左子树中所有项的值小于X中的项,而它的右子树中所有项的值大于X中的项。

如果插入序列是随机的,则平均深度是O(logN)。

如果插入序列是预先排好序的,那么会退化成链表。

一种解决方案是有一个附加平衡条件,如AVL树,红黑树(red black tree);

另一种是每次操作之后使用一个规则调整平衡,如伸展树(splay tree)。

/**
 * 二叉查找树
 * 
 * 操作的平均时间为O(logN)
 * 
 * 公有方法: 
 * void insert(T x); 
 * void remove(T x); 
 * T findMin();
 * T findMax();
 * boolean contains(T x); 
 * void makeEmpty();
 * boolean isEmpty();
 * void printTree();
 */
public class BinarySearchTree<T extends Comparable<? super T>> {

	private BinaryNode<T> root; // 唯一数据域是对树根的引用

	// 节点类
	private static class BinaryNode<T> {

		private T element;
		private BinaryNode<T> left;
		private BinaryNode<T> right;

		BinaryNode(T theElement, BinaryNode<T> lt, BinaryNode<T> rt) {
			element = theElement;
			left = lt;
			right = rt;
		}
	}

	// 构造器
	public BinarySearchTree() {
		root = null;
	}

	// 插入,调用更general的私有插入方法
	public void insert(T x) {
		root = insert(x, root);
	}

	// 删除,调用更general的remove方法
	public void remove(T x) {
		root = remove(x, root);
	}

	// 最小项,为空返回null
	public T findMin() {
		if (isEmpty())
			return null;
		return findMin(root).element;
	}

	// 最大项,为空返回null
	public T findMax() {
		if (isEmpty())
			return null;
		return findMax(root).element;
	}

	// contains
	public boolean contains(T x) {
		return contains(x, root);
	}

	//
	public void makeEmpty() {
		root = null;
	}

	//
	public boolean isEmpty() {
		return root == null;
	}

	//
	public void printTree() {
		if (isEmpty()) {
			System.out.println("Empty tree");
			return;
		} else
			printTree(root);
	}

	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;
	}
	
	private BinaryNode<T> remove(T x, BinaryNode<T> t) {
		if (t == null)
			return t; // 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) {
			// 找到右子树最小节点,把值赋给当前节点
			t.element = findMin(t.right).element;
			// 删除右子树最小节点
			t.right = remove(t.element, t.right);
		} else
			t = (t.left != null) ? t.left : t.right;
		return t;
	}

	// 只要有左儿子,就向左进行,这里用递归方式编程
	private BinaryNode<T> findMin(BinaryNode<T> t) {
		if (t == null)
			return null;
		else if (t.left == null)
			return t;
		return findMin(t.left);
	}

	// 只要有右儿子,就向右进行,这里用while循环代替递归
	private BinaryNode<T> findMax(BinaryNode<T> t) {
		if (t != null)
			while (t.right != null)
				t = t.right;
		return t;
	}

	private boolean contains(T x, BinaryNode<T> t) {

		if (t == null)
			return false;

		int compareResult = x.compareTo(t.element);
		// 这里的递归调用可以用while循环代替
		if (compareResult < 0)
			return contains(x, t.left);
		else if (compareResult > 0)
			return contains(x, t.right);
		else
			return true; // Match
	}

	// 中序遍历print,结果是从小到大输出
	private void printTree(BinaryNode<T> t) {
		if (t != null) {
			printTree(t.left);
			System.out.println(t.element);
			printTree(t.right);
		}
	}

	// 计算树高度,本程序没用到
	private int height(BinaryNode<T> t) {
		if (t == null)
			return -1;
		else
			return 1 + Math.max(height(t.left), height(t.right));
	}

	// 测试
	public static void main(String[] args) {

		BinarySearchTree<Integer> t = new BinarySearchTree<>();

		for (int i = 0; i <= 100; i++) {
			t.insert(i);
		}

		t.printTree();
		System.out.println(t.findMax());
		System.out.println(t.findMin());
		System.out.println(t.contains(101));

	}

}




你可能感兴趣的:(数据结构,递归,二叉查找树,树)