数据结构二叉搜索树BST
- 静态查找&动态查找
-
- [静态查找(Static Search)](#静态查找(Static Search))
- [动态查找(Dynamic Search)](#动态查找(Dynamic Search))
- [二叉搜索树(BST,Binary Search Tree)](#二叉搜索树(BST,Binary Search Tree))
静态查找&动态查找
静态查找(Static Search)
指:在查找过程中,查找表的内容是固定不变的,不允许插入或删除记录,只进行查找(find)操作。
关键特征:查找表在构建完成后不再发生结构变化
只支持:查找(Search)
不支持:插入(Insert)& 删除(Delete)
动态查找(Dynamic Search)
指:在查找过程中,查找表允许进行插入和删除操作,表的结构可能随操作而发生变化。
关键特征:查找表是可变的
支持:查找(Search)、插入(Insert)、删除(Delete)
需要维护结构性质(如平衡性)
二叉搜索树(BST,Binary Search Tree)
二叉搜索树(BST,Binary Search Tree),也称 二叉排序树 或 二叉查找树。
二叉搜索树是一棵二叉树,可以为空;
如果不为空,满足以下性质:
非空左子树的所有键值小于其根结点的键值。
非空右子树的所有键值大于其根结点的键值。
左、右子树都是二叉搜索树。
补充说明
BST 的关键在于:左小右大,递归成立
对 BST 进行 中序遍历,得到的是一个递增有序序列
Find查找结点
二叉搜索树的查找操作:Find
查找从根结点开始,如果树为空,返回 NULL。
若搜索树非空,则将根结点关键字与 X 进行比较,并进行不同处理:
① 若 X 小于根结点关键值,只需在左子树中继续搜索;
② 如果 X 大于根结点的关键值,在右子树中进行继续搜索;
③ 若两者比较结果相等,搜索完成,返回指向此结点的指针。
递归法

c
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; /* 查找成功,返回找到结点的地址 */
}
非递归法
由于非递归函数的执行效率高,可将"尾递归"函数改为迭代函数
实际工程与考试中,迭代版(非递归法)更高效、更常用
c
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; /* 查找失败 */
}
Find查找的效率取决于树的高度,所以我们希望这个树尽量的平衡,不要出现一边倒。
查找最大&最小结点
最大元素一定在树的最右分支的端结点上
最小元素一定在树的最左分支的端结点上

查找最小元素的递归函数
c
Position FindMin( BinTree BST )
{
if ( !BST )
return NULL; /* 空的二叉搜索树,返回 NULL */
else if ( !BST->Left )
return BST; /* 找到最左叶结点并返回 */
else
return FindMin( BST->Left ); /* 沿左分支继续查找 */
}
查找最大元素的迭代函数
c
Position FindMax( BinTree BST )
{
if ( BST )
while ( BST->Right )
BST = BST->Right; /* 沿右分支继续查找,直到最右叶结点 */
return BST;
}
二叉搜索树的插入
同一组元素,如果插入顺序不同,二叉搜索树的形态可以完全不同。
所以,这也是我们下列函数能成立的原因
c
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
第二种,删除的结点只有一个孩子结点:将其父结点的指针指向被删除结点的孩子结点
例:删除33,41的指针指向35


第三种,删除的结点有左、右两颗子树:用另一个结点代替被删除的结点,右子树的最小元素或者左子树的最大元素
例:删除41


代码
c
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;
}