简体   繁体   中英

How to remove Specific Node is Binary Search Tree?

I am trying to delete the specific Node but I don't see where the problem is.

Actually, I get the Node through the Find() and then delete it with Remove() .

The program crashes whenever Delete() fires.

bool RemoveNode(int key)
{
    if (IsEmpty())
        return false;
    Node* r = Find(key,root);
    if (r==nullptr)
        return false;
    return Remove(r);
}
bool Remove (Node* &r)
{
    if (r->left==nullptr && r->right ==nullptr)
    {
        delete r;
        r=nullptr;
        return true;
    }
    if (r->left==nullptr)
    {
        Node* temp = r->right;
        delete r;
        r=nullptr;
        r=temp;
        return true;
    }
    if (r->right==nullptr)
    {
        Node* temp = r->left;
        delete r;
        r=nullptr;
        r=temp;
        return true;
    }
    Node* Max = FindMax(r->left);
    r->data = Max->data;
    Remove(Max);

    return true;
}
Node* FindMax(Node* r)
{
    if(r->right==nullptr)
        return r;
    return FindMax(r->right);
}
Node* Find(int key, Node* &r)
{
    if (r==nullptr)
        return nullptr;

    if (r->data==key)
        return r;

    if (key < r->data)
        return Find(key,r->left);
    else
        return Find(key,r->right);
}

Clearly, your Remove() function is intended to modify the pointer to the node, independent on where it is located: instead of passing in the raw pointer, you are passing in a reference to the pointer. This way, you could update the tree's root pointer, the left or right as a component of the next. As long as you pass it in the correct reference, I think the code should work.

The variable r is actually modified in Remove() which is a local variable defined in RemoveNode() : the result of Find() is a pointer, not a reference to the relevant pointer. However, you need to modify the pointer in your tree structure pointing to the node, not an arbitrary local variable.

The fix would be the use a special version of Find()' which correctly returns a reference to the pointer rather than the pointer itself. Your recursive Find()' which correctly returns a reference to the pointer rather than the pointer itself. Your recursive Find() would be up to the task if it returned a Node*& rather than a Node*`. Since your tree doesn't seem to be balanced and stack space is relatively limited, I'd rather use a non-recursive function. Instead of returning a reference to a pointer it would maintain a pointer to a pointer to the current node instead of a pointer to the node:

Node** InternFind(int key) {
    Node** n = &this->root;
    while (*n && (*n)->key != key) {
        n = &(key < (*n)->key? (*n)->left: (*n)->right);
    }
    return n;
}

The code is untested and probably not quite right. Once you got the pointer to the pinter, however, you can just update it without dealing with where the came from:

Node** r = InternFind(key);
if (*r) {
    Remove(*r);
    return true;
}
else {
    return false;
}

Although I don't know what "if Delete() fires" means, I'd assume you have a problem with duplicate uses of delete p for the same pointer p . The code probably goes wrong long before that accessing stale nodes.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM