(七)資料結構之搜尋二叉樹的簡單實現
阿新 • • 發佈:2019-01-25
1、搜尋二叉樹的簡單定義
二叉搜尋樹(BST, Binary Search Tree), 也稱二叉排序樹或者二叉查詢樹。
定義:
a、是一顆二叉樹,可以為空,也可以不為空。
b、非空左子樹的所有鍵值小於其根結點的鍵值
c、非空右子樹的所有鍵值大於其根結點的鍵值。
d、左、右子樹都是二叉搜尋樹。
2、具體實現
2.1 基本資料結構
/* 二叉樹的基本資料結構的定義 */ typedef int ElementType; typedef struct TreeNode *BinTree; typedef BinTree Position; struct TreeNode{ ElementType Data; BinTree Left; BinTree Right; };
2.2 插入操作
/* 二叉搜尋樹的插入演算法 */ BinTree Insert( ElementType X, BinTree BST ) { if( !BST ) { /*若原樹為空,生成並返回一個結點的二叉搜尋樹*/ BST = (BinTree)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); /*遞迴插入右子樹*/ } return BST; }
2.3 刪除操作
/* 二叉樹的刪除操作,如果該結點有左右兩個子結點,則使用右子樹的最小元素替代該點 */ BinTree Delete( ElementType X, BinTree BST ) { Position Tmp = NULL; if( !BST ) printf("The BST is empty!\n"); 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; }
2.4 查詢指定元素
有兩種方式:遞迴和非遞迴方式。2.4.1 遞迴方式
/* 查詢指定元素的位置 */
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->Left ); /*在左子樹中繼續查詢*/
else
return BST; /*查詢成功,返回結點的找到結點的地址*/
}
2.4.2 非遞迴方式
/* 查詢指定元素的位置 */
Position IterFind( ElementType X, BinTree BST )
{
while(BST)
{
if( X > BST->Data )
BST = BST->Right;
else if (X < BST->Data)
BST = BST->Left;
else
return BST;
}
return NULL;
}
2.5 查詢最小值
也分為兩種方式:遞迴和非遞迴。2.5.1 遞迴方式
/* 找到這個二叉樹中的最小值的位置 */
Position FindMin( BinTree BST )
{
if( !BST ) return NULL; /*空的二叉搜尋樹,返回NULL*/
else if( !BST->Left )
return BST; /*找到最左葉結點並返回*/
else
return FindMin( BST->Left ); /*沿左分支繼續查詢*/
}
2.5.2 非遞迴方式
/* 查詢最小元素所在的位置 */
Position IterFindMin( BinTree BST )
{
if(BST )
{
/*沿左分支繼續查詢,直到最左葉結點*/
while( BST->Left) BST = BST->Left;
}
return BST;
}
2.6 查詢最大值
也分為兩種:遞迴和非遞迴。
2.6.1 遞迴方式
/* 找到這個二叉樹中的最大值的位置 */
Position FindMax( BinTree BST )
{
if( !BST ) return NULL; /*空的二叉搜尋樹,返回NULL*/
else if (!BST->Right)
return BST;
else
return FindMax( BST->Right); /*沿右分支繼續查詢*/
}
2.6.2 非遞迴方式
/* 查詢最大元素所在的位置 */
Position IterFindMax( BinTree BST )
{
if(BST )
{
/*沿右分支繼續查詢,直到最右葉結點*/
while( BST->Right ) BST = BST->Right;
}
return BST;
}
2.7 完整示例程式碼實現
/* 二叉搜尋樹的基本實現 */
#include <stdio.h>
#include <stdlib.h>
/* 二叉樹的基本資料結構的定義 */
typedef int ElementType;
typedef struct TreeNode *BinTree;
typedef BinTree Position;
struct TreeNode{
ElementType Data;
BinTree Left;
BinTree Right;
};
/* 建立一顆二叉樹, 先建立根節點,然後建立左子樹,最後建立右子樹*/
BinTree CreatBinTree()
{
ElementType data;
BinTree T;
scanf("%d", &data); // 通過控制檯獲得一個結點資料
if(0 == data) // 如果為空樹結點
{
T = NULL;
}
else // 如果為非空樹結點
{
T = (BinTree)malloc(sizeof(struct TreeNode)); // 分配一塊記憶體給根結點
if(NULL == T) return NULL;
T->Data= data;
T->Left = CreatBinTree(); // 遞迴建立左子樹
T->Right = CreatBinTree(); // 遞迴建立右子樹
}
return T; // 返回樹根結點
}
/* 銷燬一顆二叉樹 */
void DestroyBinTree(BinTree BT)
{
if (BT)
{
DestroyBinTree(BT->Left);
DestroyBinTree(BT->Right);
free(BT);
BT = NULL;
}
}
/********************************* 遞迴操作 ******************************************/
/* 查詢指定元素的位置 */
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->Left ); /*在左子樹中繼續查詢*/
else
return BST; /*查詢成功,返回結點的找到結點的地址*/
}
/* 找到這個二叉樹中的最小值的位置 */
Position FindMin( BinTree BST )
{
if( !BST ) return NULL; /*空的二叉搜尋樹,返回NULL*/
else if( !BST->Left )
return BST; /*找到最左葉結點並返回*/
else
return FindMin( BST->Left ); /*沿左分支繼續查詢*/
}
/* 找到這個二叉樹中的最大值的位置 */
Position FindMax( BinTree BST )
{
if( !BST ) return NULL; /*空的二叉搜尋樹,返回NULL*/
else if (!BST->Right)
return BST;
else
return FindMax( BST->Right); /*沿右分支繼續查詢*/
}
/* 二叉搜尋樹的插入演算法 */
BinTree Insert( ElementType X, BinTree BST )
{
if( !BST )
{
/*若原樹為空,生成並返回一個結點的二叉搜尋樹*/
BST = (BinTree)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); /*遞迴插入右子樹*/
}
return BST;
}
/* 二叉樹的刪除操作,如果該結點有左右兩個子結點,則使用右子樹的最小元素替代該點 */
BinTree Delete( ElementType X, BinTree BST )
{
Position Tmp = NULL;
if( !BST ) printf("The BST is empty!\n");
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;
}
/* 先序遞迴遍歷 */
void PreOrderTraversal( BinTree BST )
{
if( BST )
{
printf("%d ", BST->Data);
PreOrderTraversal( BST->Left );
PreOrderTraversal( BST->Right );
}
}
/* 中序遞迴遍歷 */
void InOrderTraversal( BinTree BST )
{
if( BST )
{
InOrderTraversal( BST->Left );
printf("%d ", BST->Data);
InOrderTraversal( BST->Right );
}
}
/* 後序遞迴遍歷 */
void PostOrderTraversal( BinTree BST )
{
if( BST )
{
PostOrderTraversal( BST->Left );
PostOrderTraversal( BST->Right);
printf("%d ", BST->Data);
}
}
/********************************* 非遞迴操作 ****************************************/
/* 查詢指定元素的位置 */
Position IterFind( ElementType X, BinTree BST )
{
while(BST)
{
if( X > BST->Data )
BST = BST->Right;
else if (X < BST->Data)
BST = BST->Left;
else
return BST;
}
return NULL;
}
/* 查詢最小元素所在的位置 */
Position IterFindMin( BinTree BST )
{
if(BST )
{
/*沿左分支繼續查詢,直到最左葉結點*/
while( BST->Left) BST = BST->Left;
}
return BST;
}
/* 查詢最大元素所在的位置 */
Position IterFindMax( BinTree BST )
{
if(BST )
{
/*沿右分支繼續查詢,直到最右葉結點*/
while( BST->Right ) BST = BST->Right;
}
return BST;
}
/* 程式入口 */
int main()
{
ElementType input;
BinTree node = NULL;
BinTree tree = NULL;
/* 建立一顆二叉樹 */
tree = CreatBinTree();
/* 遍歷 */
printf("************************Traversal***************************\n");
printf("Pre : "); PreOrderTraversal(tree); printf("\n");
printf("In : "); InOrderTraversal(tree); printf("\n");
printf("Post : "); PostOrderTraversal(tree); printf("\n");
/* 遞迴查詢 */
printf("************************Search******************************\n");
printf("Input a number to search : ");
scanf("%d", &input);
node = Find(input, tree);
printf("The search value is : %d\n", node->Data);
node = FindMin(tree);
printf("Min value is : %d\n", node->Data);
node = FindMax(tree);
printf("Max value is : %d\n", node->Data);
/* 非遞迴查詢 */
printf("************************IterSearch******************************\n");
printf("Input a number to search : ");
scanf("%d", &input);
node = IterFind(input, tree);
printf("The search value is : %d\n", node->Data);
node = IterFindMin(tree);
printf("Min value is : %d\n", node->Data);
node = IterFindMax(tree);
printf("Max value is : %d\n", node->Data);
/* 插入一個元素 */
printf("************************Insert******************************\n");
printf("Input a number to insert : ");
scanf("%d", &input);
tree = Insert(input, tree);
printf("Pre : "); PreOrderTraversal(tree); printf("\n");
/* 刪除一個元素*/
printf("************************Delete******************************\n");
printf("Input a number to delete : ");
scanf("%d", &input);
tree = Delete(input, tree);
printf("Pre : "); PreOrderTraversal(tree); printf("\n");
DestroyBinTree(tree); /* 銷燬一顆二叉樹 */
return 0;
}