二叉搜索树
二叉搜索树(BST, Binary Search Tree),也称二叉排序树或二叉查找树
定义
二叉搜索树:一棵二叉树,可以为空;如果不为空,满足以下性质:
- 非空左子树的所有键值小于其根结点的键值
- 非空右子树的所有键值大于其根结点的键值
- 左、右子树都是二叉搜索树
二叉搜索树操作的特别函数
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进行比较,并进行不同处理:
- 若X小于根结点键值,只需在左子树中继续搜索
- 若X大于根结点键值,在右子树中进行继续搜索
- 若两者比较结果是相等,搜索完成,返回指向此结点的指针
递归实现
Position Find(ElementType X, BinTree BST) {
if (NULL == BST) // 此时搜索树为空,返回NULL
return NULL;
if (X > BST->Data) // 在右子树中继续查找
return Find(X, BST->Right);
if (X < BST->Data)
return Find(X, BST->Left); // 在左子树中继续查找
return BST; // 查找成功,返回结点指针
}
迭代实现
由于非递归函数的执行效率高,可将“尾递归”函数改为迭代函数
Position IterFind(ElementType X, BinTree BST) {
while (BST != NULL) {
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 == NULL) // 空的二叉搜索树,返回NULL
return NULL;
if (BST->Left == NULL) // 找到最左叶结点并返回
return BST;
return FindMin(BST->Left); // 沿最左分枝继续查找
}
查找最大元素的迭代函数
Position FindMax(BinTree BST) {
if (BST != NULL) {
While (BST->Right != NULL) // 沿最右分枝继续查找,直到最右叶结点
BST = BST->Right;
}
return BST;
}
二叉搜索树的插入
关键是要找到元素应该插入的位置,可以采用与Find
类似的方法
实现
BinTree Insert(ElementType X, BInTree BST) {
if (BST == NULL) { // 若原树为空,生成并返回一个结点的二叉搜索树
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); // 递归插入右子树
// 如果X已经存在,则不进行插入
}
return BST;
}
二叉树搜索树的删除
需要考虑三种情况:
* 要删除的是叶结点:直接删除,并修改其父结点指针—置为NULL
* 要删除的结点只有一个孩子结点:将其父结点的指针指向要删除结点的孩子结点
* 要删除的结点有左右两棵子树:用另一结点替代被删除的结点
* 右子树的最小元素
* 左子树的最大元素
实现
BinTree Delete(ElementType X, BinTree BST) {
Position Tmp;
if (BST == NULL) {
printf(要删除的元素未找到);
return NULL;
}
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 != NULL && BST->Right != NULL) { // 被删除结点有左右两个子结点
Tmp = FindMin(BST->Right); // 在右子树中找最小元素填充删除结点
BST->Data = Tmp->Data;
BST->Right = Delete(BST->Data, BST->Right); // 在删除结点的右子树中删除最小元素
} else { // 被删除结点有一个或无子结点
Tmp = BST;
if (BST->Left == NULL) // 有右孩子或无子结点
BST = BST->Right;
else if (BST->Right == NULL) // 有左孩子或无子结点
BST = BST->Left;
free(Tmp);
}
}
return BST;
}