简体   繁体   English

在C ++中的删除操作中出现段错误

[英]Seg fault in my delete operation in c++

i am writing a code for a c++ assignment, it is a dictionary implementation using a binary search tree. 我正在为C ++赋值编写代码,它是使用二进制搜索树的字典实现。 My code compiles but when i try to "remove" i get a seg Fault. 我的代码可以编译,但是当我尝试“删除”时,出现段错误。 any ideas why did might be happening. 任何想法为什么会发生。 Thanks 谢谢

Here is my code 这是我的代码

// this function calls the deleteNode function where the deletion is done
void BST::deleteContent(string *word)
{
    deleteNode(word, root);
}
// a helper fuuntion for the deletecontent function
//uses recursion to find the node to be deleted
void BST::deleteNode(const string *word, Node *&nodePtr)
{
    if(word < nodePtr->word)
        deleteNode(word, nodePtr->left);
    else if(word > nodePtr->word)
        deleteNode(word, nodePtr->right);
    else
        makeDeletion(nodePtr);
}
// a helper function for the deleteNode function
void BST::makeDeletion(Node *&nodePtr)
{
    Node *tempNodePtr;

    if(nodePtr == NULL)
        cout<< "cannot delete empty node. \n";
    // if node has no right child
    else if (nodePtr->right == NULL)
        {
            tempNodePtr = nodePtr;
            nodePtr = nodePtr->left; // reattach child
            delete tempNodePtr;
        }
    else if(nodePtr-> left == NULL)
        {
            tempNodePtr = nodePtr;
            nodePtr = nodePtr->right; // reattach child
            delete tempNodePtr;
        }
    // if node has 2 children
    else
        {
            tempNodePtr = nodePtr->right;
            while (tempNodePtr->left)
                tempNodePtr = tempNodePtr->left;
            tempNodePtr->left = nodePtr->left;
            tempNodePtr = nodePtr;
            nodePtr = nodePtr->right;
            delete tempNodePtr;
        }
}

EDIT : 编辑

Thank you all!! 谢谢你们!! From your post i realised it was a good idea to check if the node was the last and had no children. 从您的帖子中,我意识到检查节点是否为最后一个节点并且没有子节点是个好主意。 I added this check in deleteNode 我在deleteNode中添加了此检查

    if((nodePtr->left) && word < nodePtr->word)
    {
        do something
    }

i did the same for the right it worked and did not throw any errors or seg faults. 我做了正确的工作,没有抛出任何错误或段错误。 Thanks so much!!!! 非常感谢!!!!

Case 1: Empty tree: 情况1:空树:

Suppose your your tree is empty: root will be nullptr . 假设您的树为空: root将为nullptr So deleteContent() will call deleteNode() with argument nullptr for nodePtr . 所以deleteContent()将调用deleteNode()与参数nullptrnodePtr

The first thing you do there is compare word with nodePtr->word without first checking that nodePtr is not nullptr . 你在那里做的第一件事是比较wordnodePtr->word不先检查nodePtrnullptr THere you have a first case of segmenation fault ! 这是您出现分割错误的第一种情况!

Case 2: Delete a word which is not in the tree: 情况2:删除不在树中的单词:

In this case, deleteNode() will be called recursively until reaching a leaf node with no descendent. 在这种情况下,将递归调用deleteNode()直到到达没有后代的叶节点。 As the searched word does not exist in the tree, it's either geater or lesser than nodePtr->word, but never equal. 由于搜索到的单词在树中不存在,因此它的名称比nodePtr-> word少,或者小于nodePtr-> word,但绝不相等。 deleteNode() will then call itself, again passing argument nullptr for nodePtr , as in case 1. Again you'll have a segmentation fault ! deleteNode()然后将调用本身,再次通过论证nullptrnodePtr ,如情况1.同样,你将有一个分割的错!

Solution to case 1 and 2: Control nullptr in deleteNode(): 情况1和2的解决方案:在deleteNode()中控制nullptr:

void BST::deleteNode(const string *word, Node *&nodePtr)
{
    if (nodePtr==nullptr) 
        cout << word << " not found in the tree\n";
    else if (word < nodePtr->word)
        ...   // the rest as in your original function 
}

makeDeletion() should now be called by deleteNode() if and only if nodePtr is not null and word==nodePtr->word . makeDeletion()现在应该叫deleteNode()当且仅当nodePtr不是null word==nodePtr->word Get rid of the first if() which should no longer be true in any case. 摆脱第一个if()在任何情况下都不再为真。 May be replace it with an assert at to verify the invariant. 可以用断言at代替它以验证不变量。

Case 3: Delete a word in the tree : 情况3:删除树中的单词:

All the three cases seem to work (even leaf nodes with two null pointers), at least if I look at my drawing of your data structure. 至少在我查看数据结构图的情况下,所有这三种情况似乎都起作用(甚至具有两个空指针的叶子节点)。

However I'd suggest to verify Node::~Node() : in all cases, you reattach the children and then you delete the old node ( temNodePtr ) without having set its children to nullptr . 但是,我建议您验证Node::~Node() temNodePtr Node::~Node() :在所有情况下,您都重新附加子节点,然后删除旧节点( temNodePtr ),而无需将其子节点设置为nullptr So I wonder whether ~Node() just destroys the node without taking care of its children (then makeDeletion() should work) or if its a recursive destructor, deleteing the node and its children (then makeDeletion() would not work because, you would delete the nodes that you've just reattached, without noticing it, thus creating a seg.fault at the first occasion). 所以,我想知道是否~Node()只是破坏节点,而不考虑其照顾孩子(当时makeDeletion()应该工作),或者如果它是一个递归的析构函数,delete一个节点和它的孩子(当时makeDeletion()是行不通的,因为你会删除您刚刚重新连接的节点,而不会引起注意,从而在第一次出现seg.fault)。

By the way, nullptr would perhap's be be more appropriate than NULL for pointers, even if NULL would work properly as well. 顺便说一句,即使NULL也可以正常工作,对于指针,nullptr也许比NULL更合适。

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

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