简体   繁体   English

c ++二进制搜索树删除

[英]c++ Binary Search tree Deletion

So, my question is I don't understand why this doesn't work. 所以,我的问题是我不明白为什么这行不通。 I commented below where it is saying that parent is never initialized when it clearly is. 我在下面的评论中说,父母显然没有初始化过。 Am I doing pointers wrong, am I getting the logic backwards am I so far off it would be better to just start from scratch? 我是在做错误的指针吗,我是在使逻辑倒退吗?我还是相距太远,最好还是从头开始? This is the most difficult assignment I have encountered so any help at all would be very beneficial. 这是我遇到的最困难的任务,因此任何帮助都是非常有益的。

void Dictionary::remove(string word)
{
if(root == NULL)
{
    cout << "list is empty\n";
    return;
}
DictionaryNode *curr = root;
DictionaryNode *parent = NULL;`

while(curr != NULL)
{
    if(curr->word == word)
        break;
    else
    {
        parent = curr;
        if(word > curr->word)
            curr = curr->right;
        else
            curr = curr->left;
    }
}
//LEAF node.
if(curr->left == NULL && curr->right == NULL)
{
    if(parent->left == curr) // Right here is an access violation. Which doesn't //make sense.
    {
        parent->left = NULL;
    }
    else
    {
        parent->right = NULL;
    }
    delete curr;
}

/*
* Node has a single child LEFT or RIGHT
*/  
if((curr->left == NULL && curr->right != NULL) || (curr->left != NULL && curr->right == NULL))
{
    if(curr->left == NULL && curr->right != NULL)
    {
        if(parent->left == curr) //if(parent->left == curr) //says parent is //not intialized
        {
            parent->left = curr->right;
            delete curr;
        }
        else
        {
            parent->right = curr->right;
            delete curr;
        }
    }

    else
    {
        if(parent->left == curr)
        {
            parent->left = curr->left;
            delete curr;
        }
        else
        {
            parent->right = curr->left;
            delete curr;
        }
    }

}

 if (curr->left != NULL && curr->right != NULL)
{
    DictionaryNode* temp; 
    if(parent == NULL || parent->left==curr)
    {  
        temp = curr->right;
        while(temp->left!=NULL)
            temp = temp->left;
        if(parent!=NULL)
            parent->left = curr->right;
        else
            root = curr->right;
        temp->left = curr->left;
        curr->left = curr->right=NULL;
        delete curr;

    } 

    else if(parent->right==curr)
    {
        temp = curr->left;
        while(temp->right!=NULL)
            temp = temp->right;
        parent->right=curr->left;
        temp->right = curr->right;
        curr->left = curr->right=NULL;
        delete curr;
    }
  }

}

1. First thing I see: 1.我首先看到的是:

while(curr != NULL)
{
 //stuff
} 

As it is written, it seems that at the end of your loop curr == NULL 如所写,似乎在循环结束时curr == NULL

Lazy me had to look at the content of your loop to notice the break. 懒惰的我不得不查看循环的内容以注意到中断。 A break could be even less noticeable with a bigger block in the loop. 如果循环中有较大的块,则中断可能更不明显。 This is not a good practice. 这不是一个好习惯。

Use a bool (eg: bool isNodeFound;), it's cheap (one bit) and makes it more clear. 使用布尔值(例如bool isNodeFound;),它便宜(一点点),而且更加清晰。 while(curr != NULL && !isNodeFound) is more clear of your intentions, at first sight, without looking at the content of your loop. while(curr!= NULL &&!isNodeFound)乍一看更清楚您的意图,而无需查看循环的内容。

2.What if indeed you don't hit the break in the loop and curr == NULL ? 2.如果确实没有在循环中中断并且curr == NULL怎么办? Your next instruction curr->left would fail! 您的下一条指令curr-> left将会失败! Seems like the Boolean will be useful again! 似乎布尔值将再次有用!

if(!isNodeFound)
{
//log error if you can "cannot remove node because it is not in dictionary"
return false; //make your function a bool to return if it succeeded or not
}

Try to analyze the rest of your code with the same state of mind, more clarity and testing, let me know if it works. 尝试以相同的心态,更清晰和测试的方式分析代码的其余部分,让我知道它是否有效。

everyone. 大家。 One day, I searched this question when i needed function to remove tree node in BST. 有一天,当我需要功能来删除BST中的树节点时,我搜索了这个问题。 So, this question is nice, i edited and checked above code then code really operated successfully. 因此,这个问题很好,我在上面的代码中进行了编辑和检查,然后代码真正成功运行了。 Above code missed some instances, follow me below explanations: 上面的代码错过了一些实例,请按照以下说明进行操作:

First, deleted node is LEAF NODE. 首先,删除的节点是LEAF NODE。 You missed a instance that node is either root or leaf node (ie BST only have a node). 您错过了一个实例,该实例的节点是根节点或叶节点(即BST仅具有一个节点)。 So, parent is NULL and parent->left/right is invalid. 因此,parent为NULL,parent-> left / right无效。

Second, deleted node has a subtree left or right. 其次,已删除的节点在左侧或右侧都有一个子树。 So, this is similar with First if deleted node is root. 因此,如果已删除节点是根节点,则此操作与“第一”相似。

Third, deleted node have left and righr subtree. 第三,删除的节点具有left和righr子树。 You considered "parent" but you shouldn't use "if(parent == NULL || parent->left==curr)" as if parent = NULL so that parent->left is invalid. 您考虑过“父母”,但不应使用“ if(父母== NULL || parent-> left == curr)”,就好像parent = NULL一样,以便parent-> left无效。 You should make " if(parent == NULL){...} else{if(parent->left == curr)...}". 您应该制作“ if(parent == NULL){...} else {if(parent-> left == curr)...}”。

Finally, use if...else-if...else instead of using if...if...if because you deleted "curr", then you won't know "curr" point anywhere and "if" next still will be checked with "curr" errors. 最后,使用if ... else-if ... else而不是使用if ... if ... if,因为您删除了“ curr”,那么您将不知道“ curr”点在何处,而“ if”仍然是将检查“ curr”错误。

Below edited code for anyone need, 下面的代码可满足任何人的需要,

void Dictionary::remove(string word)
{
    if(root == NULL)
    {
        cout << "list is empty\n";
        return;
    }
    DictionaryNode *curr = root;
    DictionaryNode *parent = NULL;

    while(curr != NULL)
    {
        if(curr->word == word)
            break;
        else
        {
            parent = curr;
            if(word > curr->word)
                curr = curr->right;
            else
                curr = curr->left;
        }
    }
    //LEAF node.
    if(curr->left == NULL && curr->right == NULL)
    {
        if (parent == NULL) {
            delete curr;
        } else {
            if(parent->left == curr) // Right here is an access violation. Which doesn't //make sense.
            {
                parent->left = NULL;
            }
            else
            {
                parent->right = NULL;
            }
            delete curr;
        }
    }

    /*
    * Node has a single child LEFT or RIGHT
    */  
    else if((curr->left == NULL && curr->right != NULL) || (curr->left != NULL && curr->right == NULL))
    {
        if(curr->left == NULL && curr->right != NULL)
        {
            if (parent == NULL) {
                    root = curr->right;
                    curr->right = NULL;
                    delete curr;
            } else {
                if(parent->left == curr) //if(parent->left == curr) //says parent is //not intialized
                {
                    parent->left = curr->right;
                    delete curr;
                }
                else
                {
                    parent->right = curr->right;
                    delete curr;
                }
            }
        }

        else
        {
            if (parent == NULL) {
                    root = curr->left;
                    curr->left = NULL;
                    delete curr;
            } else {
                if(parent->left == curr)
                {
                    parent->left = curr->left;
                    delete curr;
                }
                else
                {
                    parent->right = curr->left;
                    delete curr;
                }
            }
        }

    }
    else
    {
        DictionaryNode* temp; 
        if(parent == NULL)
        {  
            temp = curr->right;
            while(temp->left!=NULL)
                temp = temp->left;
            if(parent!=NULL)
                parent->left = curr->right;
            else
                root = curr->right;
            temp->left = curr->left;
            curr->left = curr->right=NULL;
            delete curr;

        } else {
            if(parent->left==curr){
                temp = curr->right;
                while(temp->left!=NULL)
                    temp = temp->left;
                if(parent!=NULL)
                    parent->left = curr->right;
                else
                    root = curr->right;
                temp->left = curr->left;
                curr->left = curr->right=NULL;
                delete curr;
            }
            else if(parent->right==curr)
            {
                temp = curr->left;
                while(temp->right!=NULL)
                    temp = temp->right;
                parent->right=curr->left;
                temp->right = curr->right;
                curr->left = curr->right=NULL;
                delete curr;
            }
        }
    }
}

Hope this code that can help other people when they need! 希望此代码可以在需要时帮助其他人!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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