二叉搜索樹


一、什麼是二叉搜索樹

         二叉查找樹(Binary Search Tree),(又:二叉搜索樹,二叉排序樹)它或者是一棵空樹,或者是具有下列性質的二叉樹: 若它的左子樹不空,則左子樹上所有結點的值均小於等於它的根結點的值; 若它的右子樹不空,則右子樹上所有結點的值均大於等於它的根結點的值; 它的左、右子樹也分別爲二叉排序樹


二、查詢

定義樹的結點類爲

class Node{
		int k;
		Node left = null;
		Node right = null;
		Node p = null;
	}


查找過程,從樹的根節點開始查找,輸入樹的根節點和需要查找的k值,如果結點存在,返回指向關鍵字k的結點,否則返回null。



public Node TreeSearch(Node root,int k){
		if(root==null||k==root.k)
			return root;
		if(k<root.k){
			return TreeSearch(root.left,k);
		}else{
			return TreeSearch(root.right,k);
		}	
	}



三、插入

插入和刪除會引起由二叉搜索樹的動態集合的變化。一定要修改數據結果來反映這個變化,但修改要保持二叉樹搜索樹性質成立。

public void TreeInsert(Node root,Node z){
		Node y = null;
		Node x = root;
		while(x!=null){
			y = x;
			if(z.k<x.k){
				x = x.left;
			}else{
				x = x.right;
			}
		}
		z.p = y;
		if(y==null){
			root = z;
		}else if(z.k<y.k){
			y.left = z;
		}else{
			y.right = z;
		}
		
	}


四、刪除

刪除分爲三種情況

1、如果z沒有孩子結點,那麼知識簡單地將它刪除,並修改它的父結點,用null最爲孩子了替換z

2、如果z只有一個孩子,那麼將這個孩子提升到樹中的z的位置,並修改z的父結點,用z的孩子代替z

3、如果z有兩個孩子,那麼找z的後繼y(一定在z的右子樹中)並讓其佔據樹中z的位置,z原來額右子樹部分稱爲y的右子樹,並且z的左子樹稱爲y的新的左子樹。


爲了完成刪除操作,我們先來做一下準備工作。

最大關鍵字元素和最下關鍵字元素

	/**
	 * 獲得最小值元素
	 * @param x
	 * @return
	 */
	public Node TreeMiniNum(Node x){
		while(x.left!=null){
			x = x.left;
		}
		return x;
	}
	
	/**
	 * 獲得最大值元素
	 * @param x
	 * @return
	 */
	public Node TreeMaxiNum(Node x){
		while(x.right!=null){
			x = x.right;
		}
		return x;
	}


前驅和後繼

一個結點的後繼是大於x.key的最小關鍵詞的結點,前驅是小於x.key的最大關鍵字的結點。


	/**
	 * 求後繼
	 * @param x
	 * @return
	 */
	public Node TreeSuccessor(Node x){
		if(x.right!=null){
			return TreeMiniNum(x.right);
		}
		Node y = x.p;
		while(y!=null && x == y.right){
			x = y;
			y = y.p;
		}
		
		return y;
	}
	




爲了在二叉搜索樹內移動子樹,定義一個子過程TRANSPLANT,它是用另一顆子樹替換一棵子樹併成爲其雙親的孩子結點。當TRANSPLANT用一顆以v爲根的子樹來替換一顆以u爲根的子樹時,結點u的雙親就變爲結點v的雙親,並最後v成爲u的雙親的相應孩子。


public void Transplant(Node root,Node u,Node v){
		if(u.p==null)
			root = v;
		else if(u==u.p.left)
			u.p.left = v;
		else 
			u.p.right = v;
		if(v!=null){
			v.p = u.p;
		}
	}





下面是二叉搜索樹刪除結點z的刪除過程

public void TreeDelete(Node root,Node z){
		
		//第一種情況
		if(z.left==null)
			Transplant(root, z, z.right);
		else if(z.right == null)
			Transplant(root, z, z.left);
		//第二和第三種情況
		else {
			Node y = TreeMiniNum(z.right);
			if(y.p!=z){//第三種情況
				Transplant(root, y, y.right);
				y.right = z.right;
				y.right.p = y;
			}
			//z的後繼恰好爲z的有右孩子,第二種情況
			Transplant(root, z, y);
			y.left = z.left;
			y.left.p = y;
		}
	}





在一顆高度爲h的二叉搜素樹上,實現動態集合操作Insert和Delete的運行時間均爲o(h)。



本文爲《算法導論》二叉搜索複習筆記

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章