对于大量的数据的输入,我们采用另一种大部分操作时间为log的简单数据结构,同时,在这个情况下线性列表访问的时间太慢,不适合使用,这种简单的数据结构叫做二叉查找树,其是两种库集合类TreeSet和TreeMap实现的基础。
树的定义,一棵树有一个根节点和许多的子节点,每个子节点可能有一个或者是多个子节点,并且,没有儿子的节点成为叶节点。具有相同父节点的叫做兄弟,从某个节点n1到节点nk,称为路径。一般的某个节点的高为此节点到此节点下面的分支的最长路径,也就是说,叶节点的高度为0,而深度是指,一棵树的最深的树叶的深度,该深度总是等于这棵树的高。
树的实现:
一种方式为可以在每一个节点除外的还要有一条链,使得每一个子节点的儿子指向它,不过直接的建立其之间的链是比较浪费空间的,解决方案为将每个节点的所有儿子都放在树节点的链表中。
二叉树,即每个节点的子节点数不能多于2,因此我们可以直接保存链接到它们的链,树结构的声明类似于双链列表的声明。
对于二叉查找树,其特性为,左子树的值小于根节点,右子树的值大于根节点,对于二叉查找树来说其查找最大值最小值的效率是很高的,而删除操作,会破坏树的平衡,比如我们执行删除最小值的操作,就会失去平衡,并且删除操作的效率并不高。
//BinarySearchTree class
//
//CONSTRUCTION: with no initializer
//
//**********************public operations**************
// 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
//***********************ERRORS*************************
//
// Throws UnderflowException as approprate
//Implements an unbalanced binary search tree,
//Note that all 'matching' is based on the compare to method.
//@author Zhang TiLing
public class BinarySearchTree<AnyType extends Comparable<? super AnyType>>
{
// Construct the tree
public BinarySearchTree()
{
root = null;
}
// Insert into the tree; duplicates are ignored.
// @param x the item to insert.
public void insert(AnyType x)
{
root = insert(x, root);
}
// Remove from the tree. Nothing is done if x is not found.
// @param x is the item to remove.
public void remove(AnyType x)
{
root = remove(x,root);
}
// Find the smallest item in the tree.
// @return smallest item or null if empty
public AnyType finMin()
{
if(isEmpty( ))
throw new UnderflowException();
return findMin(root).element;
}
// Find the largest item in the tree.
// @return the largest item of null of empty
public AnyType 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(AnyType 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 contains in sorted order
public void printTree()
{
if(isEmpty())
throw new UnderflowException();
else
printTree(root);
}
// Internal method to isnert into a subtree.
// @param x the item to insert.
// @parma t hte node that roots the subtree.
// @return the new root of the subtree.
private BinaryNode<AnyType> isnert (AnyType x,BinaryNode<AnyType> 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
;
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<AnyType> findMin(BinaryNode<AnyType> 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<AnyType> findMin(BinaryNode<AnyType> 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(AnyType x,BinaryNode<AnyType> 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,x.right);
else
return true;
}
// Internal method to print a subtree in sorted order.
// @param t the node that roots the subtree.
private void printTree(BinaryNode<AntType> 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<AnyType> t)
{
if(t == null)
return -1;
else
return 1 + Math.max(height(t.left),height(t.right));
}
// Basic node sorted in unbalanceed binary search tree
private static class BinaryNode<AnyType>
{
BinaryNode(AnyType theElement)
{
this(theElement,null,null);
}
BinaryNode(AnyType theElement,BinaryNode<AnyType> lt,BinaryNode<AnyType> rt)
{
element = theElement;
left = lt;
right = rt;
}
AnyType element; //The data in the node
BinaryNode<AnyType> left; //Left child
BinaryNode<AnyType> right;//Right child
}
private BinaryNode<AnyType> root;
}