**二叉树**:是一棵树,其中每个节点都不能多于两个儿子。
二叉树的一个性质是一颗平均二叉树的深度要比节点个数N小的多。分析表明,其平均深度为O(√N),而对于特殊类型的二叉树,即**二叉查找树**。其深度的平均值为O(logN)。
使二叉树成为二插查找树的性质是,对于树中的每个节点X,它的左子树所有的项值小于X中的项,而它的右子树中所有的项的值大于X。
二叉查找树要求所有的项都能够排序,要写一个一般的类,我们需要提供一个接口,这个接口就是Comparable,树中的两项总可以使用CompareTo方法进行比较。
1.contains操作
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,t.right); //递归右子树
}else{
return true;
}
}
这个要注意测试顺序,首先要对是否空树进行测试,否则,我们就会生成一个企图通过null引用访问数据域的NullPointerException的异常。剩下的测试应该使最不可能的情况安排到最后。这里用的使尾递归,也可以用while循环代替。
- findMin方法和findMax方法
这两个方法分别是返回最小值和最大值,执行findMin就是从根开始,只要有左儿子就向左进行,终点就是最小值。代码写一个findMin的递归方法和findMax的非递归方法。
private BinaryNode<AnyType> findMin(BinaryNode<AnyType> t){ //递归
if(t==null){
return null;
}else if(t.left==null){
return t;
}
return findMin(t.left);
private BinaryNode<AnyType> finMax(BinaryNode<AnyType> t){ //非递归
if(t!=null){
while(t.right!=null){
t=t.right;
}
return t;
}
}
- insert操作
插入操作思想就是为了将X插入到T树上,可以像用contains那样沿着树查找,如果找到X就什么也不做,如果没找到就将X插入到遍历的路径上的最后一个点。
private BinaryNode<AnyType> insert(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=intert(x,t.right);
}else{
; //什么也不做
}
return t;
}
- remove操作
删除方法是比较复杂的,要考虑到几种情况:
如果节点只有一片树叶,那么它可以被立即删除。如果节点有一个儿子,则可以在其父节点调整自己的链以绕过该节点后把它删除。
但是如果节点有两个儿子就比较复杂,一般的思想是用其右子树的最小数据代替该节点的数据,并且递归删除那个节点,因为右子树中的最小的节点不可能有左儿子,所以第二次删除比较容易。
private BinaryNode<AnyType> remove(AnyType x,BinaryNode<AnyType> t){
if(t==null){
return t;
}
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;
}