數據結構(三)二叉搜索樹

  這一小節主要是圍繞樹的一些典型應用展開。

什麼是二叉搜索樹

  二叉樹中一個很重要的問題就是查找問題,可以分爲兩類:靜態查找動態查找二叉搜索樹(BST,Binary Search Tree),也稱二叉排序樹或二叉查找樹

  二叉搜索樹:一棵二叉樹,可以爲空;如果不爲空,滿足以下性質:

  1. 非空左子樹的所有鍵值小於其根結點的鍵值。
  2. 非空右子樹的所有鍵值大於其根結點的鍵值。
  3. 左、右子樹都是二叉搜索樹

二叉搜索樹舉例

二叉搜索樹操作的特別函數

  • Position Find( ElementType X, BinTree BST ):從二叉搜索樹BST中查找元素X,返回其所在結點的地址;
  • Position FindMin( BinTree BST ):從二叉搜索樹BST中查找並返回最小元素所在結點的地址;
  • Position FindMax( BinTree BST ):從二叉搜索樹BST中查找並返回最大元素所在結點的地址。

BinTree Insert( ElementType X, BinTree BST )
BinTree Delete( ElementType X, BinTree BST )

二叉搜索樹的查找操作:Find

  查找從根結點開始,如果樹爲空,返回NULL。若搜索樹非空,則根結點關鍵字和X進行比較,並進行不同處理:

  1. X小於根結點鍵值,只需在左子樹中繼續搜索;
  2. 如果X大於根結點的鍵值,在右子樹中進行繼續搜索;
  3. 若兩者比較結果是相等,搜索完成,返回指向此結點的指針。

二叉查找樹

Position Find( ElementType X, BinTree BST )
{
	if( !BST ) return NULL; 
	if( X > BST->Data )
		return Find(X, BST->Right ) ; /*在右子樹中繼續查找*/
	Else if( X < BST->Data )
		return Find( x, BST->Ieft ) ; /*在左子樹中繼續查找*/
	else /* X == BST->Data */
		return BST; /*查找成功,返回結點的找到結點的地址*/
}

  上述代碼是尾遞歸形式,由於非遞歸函數的執行效率高,可將“尾遞歸”函數改爲迭代函數

Position IterFind( ElementType X, BinTree BST )
{
	while( BST ) {
		if( X > BST->Data )
			BST = BST->Right; /*向右子樹中移動,繼續查找*/
		else if( X < BST->Data )
		BST = BST->Left; /*向左子樹中移動, 繼續查找*/
		else /* X == BST->Data */
			return BST; /*查找成功,返回結點的找到結點的地址*/
	}
	return NULL; /*查找失敗*/
}

  查找的效率決定於樹的高度。

查找最大和最小元素

  最大元素一定是在樹的最右分枝的端結點上,最小元素一定是在樹的最左分枝的端結點上。

最大最小元素示意圖

  查找最小元素的遞歸函數:

Position FindMin ( BinTree BST )
{
	if( !BST ) return NULL; /*空的二叉搜索樹, 返回NULL*/
	else if ( !BST-> Left )
		return BST; / *找到最左葉結點並返回*/
	else
		return FindMin( BST->Ieft ) ; /*沿左分支繼續查找*/
}

  查找最大元素的迭代函數:

Position FindMax ( BinTree BST )
	if (BST )
		while ( BST->Right ) BST = BST->Right;
			/*沿右分支繼續查找, 直到最右葉結點*/
	return BST ;
}

二叉搜索樹的插入

  關鍵是要找到元素應該插入的位置,可以採用與Find類似的方法:

二叉搜索樹的插入

  二叉搜索樹的插入算法:

BinTree Insert( ElementType X, BinTree BST )
if( !BST ) {
		/*若原樹爲空, 生成並返回一個結點的二叉搜索樹*/
		BST = malloc(sizeof (struct TreeNode) ) ;
		BST->Data = X;
		BST->Left = BST->Right = NULL;
	}else /*開始找要插入元素的位置*/
		if( X < BST->Data )
			BST->Left = Insert( X,BST->Left) ; /*遞歸插入左子樹*/
		else if( X > BST->Data )
			BST->Right = Insert( X,BST->Right) ; /*遞歸插入右子樹*/
		/* else x已經存在,什麼都不做*/
	return BST;
}

二叉搜索樹的刪除

考慮三種情況:

  要刪除的是葉結點:直接刪除,並再修改其父結點指針—置爲NULL:

二叉搜索樹的刪除

  要刪除的結點只有一個孩子結點:

  將其父結點的指針指向要刪除結點的孩子結點

刪除只有一個孩子的節點

要刪除的結點有左、右兩棵子樹

用另一結點替代被刪除結點:右子樹的最小元素 或者 左子樹的最大元素

刪除

BinTree Delete ( E1ementType X,BinTree BST )
{ Position Tmp ;
	if( !BST ) printf ("要刪除的元素未找到") ;
	else if( X < BST->Data )
		BST->Left = Delete( x, BST->Left) ; /* 左子樹遞歸刪除*/
	else if( X > BST->Data )
		BST->Right = Delete( x, BST->Right) ; /*右子樹遞歸刪除*/
	else /*找到要刪除的結點*/
		if( BST->Left && BST->Right ) { /*被刪除結點有左右兩個子結點*/
			Tmp = FindMin( BST->Right ) ;
						/*在右子樹中找最小的元素填充刪除結點*/
			BST->Data = Tmp->Data;
			BST->Right = Delete( BST->Data, BST->Right) ; /*在刪除結點的右子樹中刪除最小元素*/
		} else { /*被刪除結點有一個或無子結點*/
			Tmp = BST;
			if( !BST->Left ) /*有右孩子或無子結點*/
				BST = BST->Right;
			else if( !BST->Right ) /*有左孩子或無子結點*/
				BST = BST- > Left;
			free( Tmp ) ;
	return BST;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章