一、描述:
二叉查找树是二叉树的一种,但它要求一个节点的左子节点小于该节点,右子节点大于该节点,因此二叉查找树里存储的值必须是可比较的。
二、代码实现:
以下是一些暴露的public
方法,大多数都调用私有方法实现。
另外还有一个隐藏的嵌套节点类。
public class BinarySearchTree<T extends Comparable<? super T>> {
//嵌套的节点类,外部无法访问
private static class BinaryNode<E>{
private E e;
private BinaryNode<E> left;
private BinaryNode<E> right;
private BinaryNode(E e,BinaryNode<E> left,BinaryNode<E> right) {
this.e = e;
this.left = left;
this.right = right;
}
private BinaryNode(E e) {
this(e,null,null);
}
}
//树的根节点
private BinaryNode<T> root;
public boolean contains(T t) {
return contains(t,root);
}
public T findMin() {
return findMin(root).e;
}
public T findMax() {
return findMax(root).e;
}
public void insert(T t) {
root = insert(t,root);
}
public void remove(T t) {
remove(t,root);
}
public void printTree() {
System.out.println("root:"+root.e);
printTree(root);
}
public boolean isEmpty() {
return root==null;
}
......
}
私有方法:findMin与findMax
查找最大值与最小值,只需要找到深度最大的右子节点和左子节点即可即可
private BinaryNode<T> findMin(BinaryNode<T> node) {
if(node==null)
return null;
//左子节点不为空则继续从左子节点找最小值
if(node.left!=null)
return findMin(node.left);
//左子节点为空,则当前值最小
return node;
}
private BinaryNode<T> findMax(BinaryNode<T> node){
if(node==null)
return null;
//右子节点不为空继续找右子节点,最右的子节点最大
if(node.right!=null)
return findMax(node.right);
//右子节点为空,当前值最大
return node;
}
私有方法:insert
实现插入操作只需要与当前节点比较,小的往左继续找,大的往右继续找,递归找到最深处插入即可,重复值将不做操作。
private BinaryNode<T> insert(T t,BinaryNode<T> node) {
//当前节点为空,已经到最深处,可创建节点插入
if(node==null)
return new BinaryNode<T>(t);
int res = t.compareTo(node.e);
if(res<0)//向左找更深处的节点
node.left = insert(t,node.left);
else if(res>0)//向右找最深处的节点
node.right = insert(t,node.right);
//插入值与当前值相同,直接返回
return node;
}
私有方法:remove
remove方法相对复杂,当移除的节点只有左子树或只有右子树时,可以直接用左子树或右子树代替移除的节点,但有两颗子树时,需要找到右子树中的最深的左子节点(即右子树中的最小值)代替当前值。
private BinaryNode<T> remove(T t,BinaryNode<T> node){
if(node==null)//节点为空,无法移除,直接返回空
return null;
int res = t.compareTo(node.e);
if(res<0)//移除值比当前值小,继续向深处移除
node.left = remove(t,node.left);
else if(res>0)//移除值比当前值大,继续向深处移除
node.right = remove(t,node.right);
//找到可移除节点,但有两颗子树
else if(node.left!=null&&node.right!=null) {
//将当前值替换为右子树中的最小值
node.e = findMin(node.right).e;
//右子树的最小值已经使用,移除右子树的最小值
remove(node.e,node.right);
}else {
//找到可移除点,且只有一颗子树或没有子树,左子树为空时用右子树替换当前节点,
//没有子树时用右子树替换当前节点(右子树此时也为空)
//左子树不为空,用左子树替换当前节点
node = node.left==null?node.right:node.left;
}
return node;
}
私有方法:printTree
这个方法靠喜好实现吧,二叉树怎么打印出来都感觉很乱
private void printTree(BinaryNode<T> node) {
//当前节点为空,直接返回
if(node==null)
return;
//打印当前节点值(用n标识当前节点)
System.out.print("n:"+node.e);
//打印左子节点和右子节点(分别yongl和r标识)
if(node.left!=null) {
System.out.print(" l:"+node.left.e);
}
if(node.right!=null) {
System.out.print(" r:"+node.right.e);
}
//当前节点及子节点打印完换行
System.out.println();
//分别将左右子节点当做当前节点打印其子节点
printTree(node.left);
printTree(node.right);
}
私有方法:contains
采用遍历树的方式找到树的最深处,有相同值返回true
private boolean contains(T t,BinaryNode<T> node) {
if(t!=null) {
//和当前值比较,小则查找左子树,大则查找右子树,相同返回true
int i = t.compareTo(node.e);
if(i<0)
contains(t, node.left);
else if(i>0)
contains(t,node.right);
else
return true;
}
return false;
}
以上就是二叉查找树的基本实现,主要采用递归实现,也可替换成循环。