二叉查詢樹及Avl樹
阿新 • • 發佈:2018-12-09
定義不再敘述,看程式
應該是這本書,我看的第二版
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);
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.min(height(k2.left), height(k2.right))+1;
k1.height=Math.min(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.min(height(k2.left), height(k2.right))+1;
k1.height=Math.min(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[] {12,5,46,48,56,15,2};
Avl<Integer>avl=new Avl<Integer>();
for(int i=0;i<a.length;i++)
avl.insert(a[i]);
System.out.println();
}
}