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

时间:2014-09-12 21:36:34

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

我正在为c ++赋值编写代码,它是使用二叉搜索树的字典实现。我的代码编译但当我尝试"删除"我得到一个段错误。任何想法为什么可能会发生。感谢

这是我的代码

// 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;
        }
}

修改

谢谢大家!!从你的帖子我意识到检查节点是否是最后一个没有孩子是一个好主意。我在deleteNode

中添加了这个检查
    if((nodePtr->left) && word < nodePtr->word)
    {
        do something
    }

我做了同样的事情 它工作,并没有抛出任何错误或seg故障。非常感谢!!!!

1 个答案:

答案 0 :(得分:1)

案例1:空树:

假设您的树为空:root将为nullptr。因此,deleteContent()会针对deleteNode()使用nullptr参数调用nodePtr

您首先要做的是将wordnodePtr->word进行比较,而不先检查nodePtr是否为nullptr。你有第一例分段故障!

案例2:删除不在树中的字词:

在这种情况下,deleteNode()将被递归调用,直到到达没有后代的叶节点。由于搜索到的单词不存在于树中,因此它或者比nodePtr-> word更小或者更小,但是永远不会相等。 deleteNode()然后会再次传递自己 nullptr的参数nodePtr,如案例1所示。再次,您将遇到分段错误!

案例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 
}
{p> makeDeletion()现在应由deleteNode()调用,当且仅当nodePtr不为空且word==nodePtr->word时。摆脱第一个if(),在任何情况下都不应该是真的。可以用断言替换它来验证不变量。

案例3:删除树中的字词:

所有这三种情况似乎都有效(即使叶子节点有两个空指针),至少如果我查看我的数据结构图。

但是我建议验证Node::~Node() :在所有情况下,您重新附加孩子,然后删除旧节点(temNodePtr)而不设置其子节点到nullptr。所以我想知道~Node()是否只是破坏节点而不关心它的子节点(然后makeDeletion()应该工作)或者如果它是一个递归析构函数,删除节点及其子节点(然后makeDeletion()将不起作用,因为你会删除你刚刚重新连接的节点,而不会注意到它,因此在第一次创建一个seg.fault)。

顺便说一句,对于指针,nullptr会比NULL更合适,即使NULL也能正常工作。