先提供一个二叉树的结构
/* 二叉树的二叉链表结点结构定义 */
typedef struct BiTNode
{
int data; //结点数据
struct BiTNode* lchild,*rchild; //左右孩子指针
}BiTNode,*BiTree;
二叉排序树的查找
//二叉排序树的查找
/* 递归查找二叉排序树T中是否存在key */
/* 指针 f 指向 T 的双亲,其初始调用值为NULL*/
/* 若查找成功,则指针 p 指向该数据元素结点,并返回TRUE */
/* 否则指针p指向查找路径上访问的最后一个结点并返回FALSE */
int SearchBST(BiTree T, int key,BiTree f,BiTree *p)
{
// 查找不成功
if (!T) {
*p = f;
return FALSE;
}
else if (key == T->data) {
*p = T;
return TRUE;
}
else if (key < T->data)
{
return SearchBST(T->lchild, key, T, p);
}
else {
return SearchBST(T->rchild, key, T, p);
}
}
二叉排序树的插入操作
//二叉排序树的插入操作
/* 当二叉排序树T中不存在关键字等于key的数据元素时, */
/* 插入key并返回TRUE,否则返回FALSE */
int InsertBST(BiTree *T,int key)
{
BiTree p, s;
if (!SearchBST(*T, key, NULL, &p)) //查找不成功
{
s = (BiTree)malloc(sizeof(BiTNode));
s->data = key;
s->lchild=s->rchild = NULL;
if (!p)
{
*T = s; //插入s为根结点(这是起初整个树为空的情况)
}
else if (key < p->data)
{
p->lchild = s; //插入s为左孩子
}
else
p->rchild = s; //插入s为右孩子
return TRUE;
}
else {
return FALSE;
}
}
根据我们对删除结点三种情况的分析
- 叶子结点
- 仅有左或者右子树
- 左右子树都有的结点,我们来看代码,下面这个算法是递归方式对二叉排序树 T 查找 key,查找到时删除
//二叉排序树的删除操作
/* 从二叉排序树中删除结点p,并重接他的左子树或右子树 */
int Delete(BiTree *p)
{
BiTree q, s;
if ((*p)->rchild == NULL) //右子树空则只需要重接它的左子树
{
q = *p; *p = (*p)->lchild; free(q);
}else if ((*p)->lchild == NULL) //左子树空则只需要重接它的右子树
{
q = *p; *p = (*p)->rchild; free(q);
}
else // 左右子树均不空
{
q = *p; s = (*p)->lchild;
while (s->rchild) /* 转左,然后向右到尽头(找待删除结点的前驱) */
{
q = s; s = s->rchild;
}
(*p)->data = s->data; /* s指向被删结点的直接前驱 */
if (q != *p)
q->rchild = s->lchild; //重接q的右子树
else
q->lchild = s->lchild; //重接q的左子树
free(s);
}
return TRUE;
}
/* 若二叉排序树T中存在关键字等于key的数据元素时,则删除该数据元素结点, */
/* 并返回TRUE;否则返回FALSE */
int Delete(BiTree *p);
int DeleteBST(BiTree* T, int key)
{
if (!T) /* 不存在关键字等于key的数据元素 */
{
return FALSE;
}
else
{
if (key == (*T)->data) // 找到关键字等于key的数据元素
return Delete(T);
else if (key < (*T)->data)
return DeleteBST(&(*T)->lchild,key);
else
return DeleteBST(&(*T)->rchild, key);
}
}