1. 程式人生 > >二叉查詢樹及Avl樹

二叉查詢樹及Avl樹

定義不再敘述,看程式
應該是這本書,我看的第二版
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();
	}

}