数据结构 浙大MOOC--树(中)
二叉搜索树的查找操作
查找从根节点开始,如果树为空,返回NULL,
如果搜索树非空,则根节点关键字和X进行比较,并进行不同处理:
- 如果x小于根节点键值,只需在左子树中继续搜索
- 如果x大于根节点的键值,在右子树中进行继续搜索
- 若两者比较结果是相等,搜索完成,返回指向此节点的指针
//二叉搜索树的查找操作
//递归实现
Position Find(ElementType X, BinTree BST)
{
if(!BST) //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 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
}
else if (!BST->Left) //当前节点的左子树为空,则此时已经递归到了最左端
{
return BST; //找到最左叶节点并返回
}
else
{
return FindMin(BST->Left); //递归搜索左子树,沿左分支继续查找
}
}
//查找最小元素的迭代函数
Position FindMin(BinTree BST)
{
if(BST != NULL)
{
while(BST->Left != NULL)
{
BST = BST->Left;
}
}
return BST;
}
//查找最大元素的递归函数
Position FindMax(BinTree BST)
{
if(BST == NULL)
{
return NULL;
}
else if(BST->Right == NULL)
{
return BST; //找到最右节点并返回
}
else
{
return FindMax(BST->Right);
}
}
//查找最大元素的迭代函数
Position FindMax(BinTree BST)
{
if(BST) //BST不为空
{
while(BST->Right) //沿右分支继续查找,直到最右叶节点
{
BST = BST->Right;
}
}
return BST;
}
二叉搜索树的插入
关键是要找到元素应该插入的位置,可以采用与Find类似的方法
递归实现
//二叉搜索树的插入算法
//BST始终是该树的根节点,
BinTree Insert(ElementType X, BinTree BST)
{
if(!BST) //若原树为空,生成并返回一个节点的二叉搜索树
{
BST = malloc(sizeof(stuct 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;
}