定义不再叙述,看程序
应该是这本书,我看的第二版
https://book.douban.com/subject/10530466/
下面是二叉查找树,我认为比较好的一点是在插入的时候返回修改的子树,代替了c里面的指针,这是我看c数据结构想改写为java时所没有想到的。
还有一点,用户在插入时是不知道root的,而插入函数需要root,所以要有两个插入函数,一个是外部的,只传入值;一个是内部的,传入值和子树的根。书上直接写成了函数重载。
package copy_from_book;
import java.lang.reflect.UndeclaredThrowableException;
public class BinarySearchTree<AnyType extends Comparable<?super AnyType>> {
//内部类
//.定义在别的类内部、函数内部的类。
//.内部类能直接访问外部的全部资源。
//.外部是函数时,只能访问那个函数里 final的变量。
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;
BinaryNode<AnyType> left;
BinaryNode<AnyType> right;
}
private BinaryNode<AnyType> root;
public BinarySearchTree()
{root=null;}
public void makeEmpty()
{root=null;}
public boolean isEmpty()
{return root==null;}
//下面很多函数重载,是因为
//从外部使用函数public,是不知道root
//而调用这些函数(很多次递归,又要用到子树的root)
//所以public去调用private的重载函数
public boolean contains(AnyType x)
{return contains(x,root);}
public AnyType findMin()
{
if(isEmpty()) throw new UndeclaredThrowableException(null);
return findMin(root).element;
}
public AnyType findMax()
{
if(isEmpty()) throw new UndeclaredThrowableException(null);
return findMax(root).element;
}
public void insert(AnyType x)
{root=insert(x,root);}
public void remove(AnyType x)
{root=remove(x,root);}
private boolean contains(AnyType x,BinaryNode<AnyType>t)
{
if(t==null)
return false;
int compareResult=x.compareTo(t.element);
//返回x-t.element的符号函数
if(compareResult<0)
return contains(x,t.left);
else if(compareResult>0)
return contains(x,t.right);
else
return true;
}
private BinaryNode<AnyType> findMin(BinaryNode<AnyType>t)
{
if(t==null)
return null;
else if(t.left==null)
return t;
else
return findMin(t.left);
}
private BinaryNode<AnyType> findMax(BinaryNode<AnyType>t)
{
if(t!=null)
{
while(t.right!=null)
t=t.right;
}
return t;
}
private BinaryNode<AnyType> insert(AnyType x,BinaryNode<AnyType>t)
{
//return the new root of the subtree这个方法太好了
//用了这个就可以避免C里面实现时需要传入指针来改变参数
/* * @param x the item to insert * @param t the node that roots the subtree * @return the new root of the subtree */
if(t==null)
return new BinaryNode<AnyType>(x,null,null);
int compareResult=x.compareTo(t.element);
//返回x-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;
}
private BinaryNode<AnyType> remove(AnyType x,BinaryNode<AnyType>t)
{
/* *@param x the item to remove *@param t the node that roots the subtree *@return the new root of the subtree */
//如果删除的次数不多,可以采用“懒惰删除”:
//当一个元素要被删除时,保留元素在树里
//只是标记为删除。在有重复项时常用。
if(t==null)
return t;//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的元素为右子树最小元素
//删除右子树的最小元素
t.element=findMin(t.right).element;
t.right=remove(t.element,t.right);
}
else
t=(t.left!=null)?t.left:t.right;
return t;
}
public static void main(String []args)
{
int m[]=new int[] {1,25,6,8,5,4,2};
BinarySearchTree<Integer> b=new BinarySearchTree<Integer>();
for(int i=0;i<m.length;i++)
{
b.insert(m[i]);
}
System.out.println();
}}
AVL树
书上写的不全,我又补充了一些。(原来写错了,我又改正了)
package df;
public class Avl<AnyType extends Comparable<?super AnyType>> {
private static class AvlNode<AnyType>
{
AvlNode(AnyType theElement)
{this(theElement,null,null);}//调用下面的构造器
AvlNode(AnyType theElement,AvlNode<AnyType>lt,
AvlNode<AnyType>rt)
{element=theElement;
left=lt;
right=rt;}
AnyType element;
AvlNode<AnyType> left;
AvlNode<AnyType> right;
int height;
}
private AvlNode<AnyType> root;
private int height(AvlNode<AnyType> t)
{
return t==null?-1:t.height;
}
public void insert(AnyType x)
{
root=insert(x,root);
}
private AvlNode<AnyType> insert(AnyType x,AvlNode<AnyType>t)
{
/* * @param x the item to insert * @param t the node that roots the subtree * @return the new root of the subtree */
if(t==null)
return new AvlNode<AnyType>(x,null,null);
int compareResult=x.compareTo(t.element);
if(compareResult<0)
{
t.left=insert(x,t.left);
if(height(t.left)-height(t.right)==2)
if(x.compareTo(t.left.element)<0)
t=rotateWithLeftChild(t);
else
t=doubleWithLeftChild(t);
}
else if(compareResult>0)
{
t.right=insert(x,t.right);
if(height(t.right)-height(t.left)==2)
if(x.compareTo(t.right.element)>0)
t=rotateWithRightChild(t);
else
t=doubleWithRightChild(t);
}
else;//do nothing
t.height=Math.max(height(t.left), height(t.right))+1;
return t;
}
private AvlNode<AnyType> rotateWithLeftChild(AvlNode<AnyType>k2)
{//插在左子树的左边
AvlNode<AnyType>k1=k2.left;
k2.left=k1.right;
k1.right=k2;
k2.height=Math.max(height(k2.left), height(k2.right))+1;
k1.height=Math.max(height(k1.left), k2.height)+1;
return k1;
}
private AvlNode<AnyType> rotateWithRightChild(AvlNode<AnyType>k2)
{//插在右子树的右边
AvlNode<AnyType>k1=k2.right;
k2.right=k1.left;
k1.left=k2;
k2.height=Math.max(height(k2.left), height(k2.right))+1;
k1.height=Math.max(height(k1.right), k2.height)+1;
return k1;
}
private AvlNode<AnyType> doubleWithLeftChild(AvlNode<AnyType> k3)
{//插在左子树右边
k3.left=rotateWithRightChild(k3.left);
return rotateWithLeftChild(k3);
}
private AvlNode<AnyType> doubleWithRightChild(AvlNode<AnyType> k3)
{//插在右子树左边
k3.right=rotateWithLeftChild(k3.right);
return rotateWithRightChild(k3);
}
public static void main(String args[])
{
int a[]=new int[] {3,2,1,4,5,6,7,16,15,14,13,12,11,10,8,9};
Avl<Integer>avl=new Avl<Integer>();
for(int i=0;i<a.length;i++)
avl.insert(a[i]);
System.out.println();
System.out.println();
}
}