二叉搜索树
查找问题
- 静态查找和动态查找
- 针对动态查找,数据如何组织?
二叉搜索树的性质
- 非空左子树的所有键值小于其根结点的键值。
- 非空右子树的所有键值大于其根结点的键值。
- 左、右子树都是二叉搜索树。
二叉搜索树的特别函数
Position Find( ElementType X, BinTree BST )
Position FindMin( BinTree BST )
Position FindMax( BinTree BST )
BinTree Insert( ElementType X, BinTree BST )
BinTree Delete( ElementType X, BinTree BST )
二叉搜索树的查找操作Find
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 // 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->Left); // 沿左分枝极限查找
}
查找最大元素的迭代函数
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( ElementType 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 );
}
retutn ( Tmp );
}
BST = BST->Right;
else if( !BST->Right )
BST = BST->Left;
free( Tmp );
}
retutn ( Tmp );
}