《大话数据结构》二叉排序树代码错误

《大话数据结构》二叉排序树,删除某结点的函数

/* 从二叉排序树中删除结点p,并重接它的左或右子树。 */
Status 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;
}
 if((*p)->rchild==NULL) /* 右子树空则只需重接它的左子树(待删结点是叶子也走此分支) */
{
q=*p; *p=(*p)->lchild; free(q);
}
else if((*p)->lchild==NULL) /* 只需重接它的右子树 */
{
q=*p; *p=(*p)->rchild; free(q);
}

当结点的右子树为空时的操作,q=*p; *p=(*p)->lchild; free(q);

红色部分代码的操作没有任何作用,本意是将p结点的左子树接到p结点的父节点的左子树或者右子树上,但是这样里的操作

并没有达到需求。因为这个函数中并没有获得p结点的父节点。经过我多次测试,发现了以上问题。


正确的函数如下:

BSTNode  * delBST(PBSTree t, int  k)
{
    BSTNode  *p, *f,*s ,*q;
    p=t;
    f=NULL;
    while(p)  /*查找关键字为k的待删结点p*/
    {
        if(p->data==k )  break;  /*找到则跳出循环*/
        f=p;   /*f指向p结点的双亲结点*/
        if(p->data>k)
            p=p->left;
        else
            p=p->right;
    }
    if(p==NULL)  return t;  /*若找不到,返回原来的二叉排序树*/
    if(p->left==NULL)  /*p无左子树*/
    {
        if(f==NULL)//父节点不存在
            t=p->right;  /*p是原二叉排序树的根*/
        else
            if(f->left==p)  /*p是f的左孩子*/
                f->left=p->right ;  /*将p的右子树链到f的左链上*/
            else  /*p是f的右孩子*/
                f->right=p->right ;  /*将p的右子树链到f的右链上*/
            free(p);  /*释放被删除的结点p*/
    }
    else  /*p有左子树*/
    {
        q=p;
        s=p->left;
        while(s->right)  /*在p的左子树中查找最右下结点*/
        {
            q=s;
            s=s->right;
        }
        if(q==p)
            q->left=s->left ;  /*将s的左子树链到q上*/
        else
            q->right=s->left;
        p->data=s->data;  /*将s的值赋给p*/
        free(s);
    }
    return t;
}  /*DelBST*/
参考了耿国华老师写的 数据结构 C语言描述 》。


你可能感兴趣的:(数据结构与算法)