1. 程式人生 > >二叉樹的查詢演算法

二叉樹的查詢演算法

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">二叉查詢樹</span><span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">的基本演算法依賴的底層資料結構是二叉樹,該演算法實現的方法有:</span>

get()查詢

put()插入

min(),max()最小,最大值

ceiling(),floor()向上,向下取整

select(),rank()選擇,排序的方法

deleteMin(),deleteMax()刪除最小,最大值

delete()刪除指定的元素

keys()遍歷

public class BinarySearchTree<Key extends Comparable<Key>,Value> {
	
	private Node root;
	
	private class Node{
		Key key;
		Value value;
		Node left,right;
		int N;
		
		public Node(Key key,Value value,int N){
			this.key = key;
			this.value = value;
			this.N = N;
		}
	}
	
	//獲取當前二叉樹的節點個數
	public int size(){
		return size(root);
	}
	private int size(Node x){
		if(x==null){
			return 0;
		}
		return x.N;
	}
	
	//根據傳入的鍵,查詢並返回對應的值
	public Value get(Key key){
		return get(root,key);
	}
	private Value get(Node x,Key key){
		if(x==null){
			return null;
		}
		int tmp = key.compareTo(x.key);
		if(tmp<0){
			return get(x.left,key);
		}
		if(tmp>0){
			return get(x.right,key);
		}
		
		return x.value;
	}
	
	//插入節點,找到則更新,否則新建一個節點,並更新每個節點的計數器
	public void put(Key key,Value value){
		root = put(root,key,value);
	}
	private Node put(Node x,Key key,Value value){
		if(x==null){
			return new Node(key,value,1);
		}
		int tmp = key.compareTo(x.key);
		if(tmp<0){
			x.left = put(x.left,key,value);
		}
		if(tmp>0){
			x.right = put(x.right,key,value);
		}
		if(tmp==0){
			x.value = value;
		}
		x.N = size(x.left)+size(x.right)+1;
		return x;
	}
	
	//min(),max()這兩種方法在二叉樹為空時會出現異常,因為該演算法在設計的時候就沒有考慮這個問題
	public Key min(){
		return min(root).key;
	}
	private Node min(Node x){//這裡只是找出節點
		if(x.left!=null){
			return min(x.left);
		}
		return x;
	}
	
	//找出最大的節點
	public Key max(){
		return max(root).key;
	}
	private Node max(Node x){
		if(x.right!=null){
			return max(x.right);
		}
		return x;
	}
	
	//找出大於等於該元素的最小元素,函式輸入該 元素的鍵,找出符合結果的鍵並返回
	public Key ceiling(Key key){
		Node t = ceiling(root,key);
		if(t==null){
			return null;
		}
		return t.key;
	} 
	private Node ceiling(Node x,Key key){
		if(x==null){
			return null;
		}
		int temp = key.compareTo(x.key);
		if(temp==0){
			return x;
		}
		if(temp>0){
			return ceiling(x.right,key);
		}
		Node t = ceiling(x.left,key);
		if(t==null){
			return x;//這裡為什麼敢直接把x返回回去?因為至少有根節點是比要查詢的節點大的
		}else{
			return t;
		}
		
	}
	
	//找出小於等於該元素的最大元素,函式輸入該元素的鍵,找出符合結果的鍵並返回
	public Key floor(Key key){
		Node t = floor(root,key);
		if(t==null){
			return null;
		}
		return t.key;
	}
	private Node floor(Node x,Key key){
		if(x==null){
			return null;
		}
		int temp = key.compareTo(x.key);
		if(temp==0){
			return x;
		}
		if(temp<0){
			return floor(x.left,key);
		}

		Node t = floor(x.right,key);
		if(t==null){
			return x;
		}else{
			return t;
		}
	}
	
	//函式輸入序列數值,函式返回二叉樹中排名為該序列數值的節點的鍵
	public Key select(int n){
		return select(root,n).key;
	}

	private Node select(Node x,int n){
		if(x==null){
			return null;
		}
		int tmp = size(x.left);
		if(n<tmp){
			return select(x.left,n);
		}
		if(n>tmp){
			return select(x.right,n-tmp-1);
		}
		return x;
		 
	}
	
	//函式輸入鍵,在二叉樹中找到該鍵對應的序列數值,並返回
	public int rank(Key key){
		return rank(root,key);
	}
	private int rank(Node x,Key key){
		if(x==null){
			return 0;
		}
		int tmp = key.compareTo(x.key);
		if(tmp<0){
			return rank(x.left,key);
		}
		if(tmp>0){
			return 1+size(x.left)+rank(x.right,key);
		}
		return size(x.left);
	}
	
	//刪除最小元素
	public void deleteMin(){
		root = deleteMin(root);
	}
	private Node deleteMin(Node x){
		if(x.left==null){
			return x.right;
		}
		x.left = deleteMin(x.left);
		x.N = size(x.left) + size(x.right) + 1;//更新節點計數器
		return x;
	}
	//刪除最大元素
	public void deleteMax(){
		root = deleteMax(root);
	}
	private Node deleteMax(Node x){
		if(x.right==null){
			return x.left;
		}
		x.right = deleteMax(x.right);
		x.N = size(x.left) + size(x.right) +1;
		return x;
	}
	
	//
	public void delete(Key key){
		root = delete(root,key);
	}
	private Node delete(Node x,Key key){
		if(x==null){
			return null;
		}
		int tmp = key.compareTo(x.key);
		if(tmp<0){
			x.left = delete(x.left,key);
		}
		if(tmp>0){
			x.right = delete(x.right,key);
		}
		if(tmp==0){
			if(x.left==null){
				return x.right; 
			}else if(x.right==null){
				return x.left;
			}
			//這裡已經找到要刪除的元素了
			Node t = x;
			x = min(t.right);
			x.left = t.left;
			x.right = deleteMin(t.right);
		}
		x.N = size(x.left)+size(x.right)+1;
		return x;
	}
	
	//查詢指定範圍的元素的方法
	public Iterable<Key> keys(){
		return keys(min(),max());
	}
	private Iterable<Key> keys(Key lo,Key hi){
		Queue<Key> queue = new Queue<Key>();
		keys(queue,root,lo,hi);
		return queue;
	}
	private void keys(Queue<Key> queue,Node x,Key lo,Key hi){
		if(x==null){
			return;
		}
		int tmplo = lo.compareTo(x.key);
		int tmphi = hi.compareTo(x.key);
		if(tmplo<0){
			keys(queue,x.left,lo,hi);
		}
		if(tmplo<=0 && tmphi>=0){
			queue.enqueue(x.key);
		}
		if(tmphi>0){
			keys(queue,x.right,lo,hi);
		}
	}	
}