在二进制搜索树中删除节点时出错

时间:2014-04-28 08:35:42

标签: c++ c binary-tree binary-search-tree

我在BST中移除节点时遇到问题,当节点同时有两个子节点是我的删除代码时:

void remove(int val)
        {
            treeNode *ptr=root,*prev=root;
            if(root->data==val)
            {
                if(root->left==NULL &&root->right==NULL)
                    root=NULL;
                else if(root->left==NULL)
                {
                    root=root->right;
                    delete ptr;
                }
                else if(root->right==NULL)
                {
                    root=root->left;
                    delete ptr;
                }
                else 
                {                   

                    swap(root,root->left);
                    delete root->left;
                    root->left=NULL;

                }
                return;
            }
            else
            {
            while(ptr->data!=val)
                 {
                    prev=ptr;
                    if(val<ptr->data)
                        ptr=ptr->left;
                    else if(val>ptr->data)
                        ptr=ptr->right;
                 }
                if(ptr->left==NULL && ptr->right==NULL)
                {
                    if(prev->left==ptr)
                        prev->left=NULL;
                    else if(prev->right==ptr)
                        prev->right=NULL;
                    delete ptr;
                    ptr=NULL;
                }
                else if(ptr->left==NULL)
                {

                    root=root->right;
                    delete ptr;
                }
                else if(ptr->right==NULL)
                {

                    root=root->left;
                    delete ptr;
                }
                else
                {
                    swap(ptr,ptr->left);
                    delete ptr->left;
                    ptr->left=NULL;

                }
        }
    }

某些测试用例已成功通过,例如:

3
3 4 5
1 
d 3

5
21 16 78 1 22
2
i 20 d 16

但是这样的输入会使程序终止

3
3 2 1
1
d 2

可以查看完整代码here

2 个答案:

答案 0 :(得分:1)

您的问题在于remove-method的“else”分支中的以下几行:

            else if(ptr->left==NULL)
            {

                root=root->right;
                delete ptr;
            }
            else if(ptr->right==NULL)
            {

                root=root->left;
                delete ptr;
            }

可能你忘了在复制和粘贴第一个案例后实现这些。快速入侵让我想到了这个:

// the node we found has only a single child
else if(ptr->left==NULL || ptr->right==NULL)
{
    // we need to re-add the non-empty sub-tree
    treeNode *partialTree = (ptr->left == NULL) ? ptr->right : ptr->left; 
    // add the sub-tree on the place where ptr was linked
    if (prev->left == ptr)
        prev->left = partialTree;
    else
        prev->right = partialTree;
    delete ptr;
}

答案 1 :(得分:0)

您的remove功能错误。在原始代码中,您始终修改root而不是ptr的子指针。如果一个节点有2个孩子你就不会推广继任者。阅读有关删除有两个孩子的BST节点的信息。

此外,我创建了一个sentinal节点,这样您就不必检查在根节点发生的删除。使用此构造函数

#include<limits.h>
binarySearchTree()
{
    root=new treeNode;
    root->data=INT_MAX;
    root->right=NULL;
    root->left=NULL;
}

void remove(int val)
{        
    treeNode *ptr=root,*prev=root;

    while(ptr->data!=val)
    {
            prev=ptr;
            if(val<ptr->data)
                    ptr=ptr->left;
            else if(val>ptr->data)
                    ptr=ptr->right;
    }
    if(ptr->left==NULL && ptr->right==NULL)
    {
        if(prev->left==ptr)
                prev->left=NULL;
        else if(prev->right==ptr)
                prev->right=NULL;
        delete ptr;
        ptr=NULL;
    }
    else if(ptr->left==NULL)
    {
        if(prev->left==ptr)
        {
            prev->left = ptr->right;    
        }
        else
        {
            prev->right = ptr->right;    
        }
        delete ptr;
    }
    else if(ptr->right==NULL)
    {
        if(prev->left==ptr)
        {
            prev->left = ptr->left;    
        }
        else
        {
            prev->right = ptr->left;    
        }
        delete ptr;
    }
    else //two children. Get the right Child's leftmost node (say X) and set ptr->data := X->data. Then delete X
    {
        treeNode* rChild = ptr->right;
        treeNode* rChildParent = ptr;
        while(rChild->left != NULL)
                    {
                        rChildParent=rChild;
                        rChild = rChild->left;
                    }
                    ptr->data=rChild->data;
                    if(rChildParent == ptr)
                    {
                        ptr->right=rChild->right;
                    }
                    else
                    {
                        rChildParent->left=rChild->right;
                    }
                    delete rChild;         
    }
}