查找の搜索二叉树
浙江大学数据结构与算法
1. 查找算法
1. 通用查找算法
/* 二叉搜索树数据结构 */
typedef struct BiNode
{
ElemType data;
struct BiNode *lchild,*rchild;
}BiNode,*BiTree;
/* 尾递归的实现方式 */
Position Find(ElemType key, BiTree BST)
{
if(BST==NULL)
return NULL;
if(key < BST->data)
{
return Find(key, BST->lchild);
}
else if(key > BST->data)
{
return Find(key, BST->rchild);
}
else
return BST;
}
/* 循环迭代的实现方式 */
Position Find(ElemType key, BiTree BST)
{
while(BST)
{
if(key < BST->data)
BST=BST->lchild;
else if(key > BST->rchild)
BST=BST->rchild;
else
return BST;
}
return NULL;
}
//此时查找效率决定于树的高度
2. 最大/最小元素查找算法
/* 循环迭代查找最大元素 */
Position FindMax(BiTree BST)
{
if(BST)
while(BST->rchild) BST=BST->rchild;
return BST;
}
/* 递归实现查找最小元素 */
Position FindMin(BiTree BST)
{
if(!BST) return NULL;
else if(!BST->lchild) //此时已经达到最左边叶子结点
return BST;
else
return FindMin(BST->lchild);
}
2. 插入
BiTree Insert(ElemType key, BiTree BST)
{
if(!BST)
{
BST = (BiTree)malloc(sizeof(BiNode));
BST->data = key;
BST->lchild = BST->rchild = NULL;
}
else
{
if(key > BST->data)
return Insert(key, BST->lchild)
else
return Insert(key, BST->rchild);
}
return BST;
}
程序递归调用分析:
假设要插入的元素是35,要插入的树是:
程序执行过程中,经历了:
三次递归调用:寻找合适的插入/挂载点;
三次递归返回:依次完成结点的挂载;
程序开始运行:
第一次递归调用:
第二次递归调用:
第三次调用:
第一次递归返回:
第二次返回调用:
第三次返回调用:
至此,所有的递归均完成,得到的BST指向根节点,此时的二叉搜索树已经是插入元素之后的。
3. 删除
二叉搜索树的删除有三种情况:
- 待删除结点是叶节点:直接删除,将其父节点指针置空
- 待删除结点仅有一个孩子结点:将其父节点的指针指向要删除结点的孩子结点
- 待删除结点有左右两颗子树:用另一结点替代被删除结点,左子树最大结点或者右子树最小结点。这样做其实就是把这种情况转化为第二种情况,在代码里更能体现出这一思想,具体如下:
(用右子树最小元素替代)
(用左子树最大元素替代)
<补充>:
左子树的最大元素一定没有右子树;
右子树的最小元素一定没有左子树;
Codes:
BiTree Delete(ElemType key, BiTree BST)
{
Position Tmp;
if(!BSP) printf("要删除的元素为找到!\n");
else if(key < BST->data)
BST->lchild = Delete(key, BST->lchild);
else if(key > BST->data)
BST->rchild = Delete(key, BST->rchild);
else //找到要删除的结点
if(BST->lchild && BST->rchild)
{
Tmp=FindMin(BST->rchild);
BST->data=Tmp->data;
BST->rchild=Delete(BST->data, BST->rchild);
}else {
Tmp=BST;
if(!BST->lchild)
BST = BST->rchild;
else if(!BST->rchild)
BST = BST->lchild;
free(Tmp);
}
return BST;
}