什么是二叉搜索树
二叉搜索树(BST)也称为二叉排序树或二叉查找树。
二叉搜索树:一棵二叉树,可以为空;如果不为空,满足以下性质。
- 非空左子树的键值小于其根结点的键值。
- 非空右子树的键值大于其根结点的键值。
- 左右子树都是二叉搜索树。
二叉搜索树的查找操作
查找从根结点开始,如果树为空,返回NULL。
若树非空,则根结点关键字和X进行比较,并进行处理:
- 若X小于根结点的值,只需要在左子树中继续搜索。
- 若X大于根结点的值,在右子树中继续搜索。
- 若两者比较结果相等,搜索完成,返回指向此结点的指针。
-
Position Find ( ElementType X, BinTree BST )
-
{
-
if( !BST )
return
NULL;
//查找失败
-
if( X > BST->Data )
//如果X大于根结点的值,到右子树中查找
-
return Find( X, BST->Right );
-
else
if ( X < BST->Data )
//否则,在左子树中查找
-
return Find( X, BST->Left );
-
else
//如果相等,则查找成功,返回结点的地址
-
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
-
return BST;
-
}
-
return
NULL;
-
}
查找最大和最小值
最大元素一定是在树的最右分支的端结点上
最小元素一定是在树的最左分支的端结点上
-
//查找最小值的递归算法
-
Position FindMin( BinTree BST )
-
{
-
if( !BST )
return
NULL;
//空的二叉树返回NULL
-
if( !BST->Left ){
//找到最左结点并返回
-
return BST;
-
}
else{
//如果存在左孩子就继续查找
-
return FindMin( BST->Left );
-
}
-
}
-
-
//查找最大值的迭代算法
-
Position FindMax( BinTree BST )
-
{
-
if( BST )
//一直向右查找
-
while( BST->Right ) BST = BST->Right;
-
return BST;
-
}
二叉搜索树的插入
-
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 );
-
}
-
}
-
return BST
-
}