i am writing a code for a c++ assignment, it is a dictionary implementation using a binary search tree. 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
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:
Suppose your your tree is empty: root
will be nullptr
. So deleteContent()
will call deleteNode()
with argument nullptr
for nodePtr
.
The first thing you do there is compare word
with nodePtr->word
without first checking that nodePtr
is not nullptr
. THere you have a first case of segmenation fault !
Case 2: Delete a word which is not in the tree:
In this case, deleteNode()
will be called recursively until reaching a leaf node with no descendent. As the searched word does not exist in the tree, it's either geater or lesser than nodePtr->word, but never equal. deleteNode()
will then call itself, again passing argument nullptr
for nodePtr
, as in case 1. Again you'll have a segmentation fault !
Solution to case 1 and 2: Control nullptr in deleteNode():
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
. Get rid of the first if() which should no longer be true in any case. May be replace it with an assert at to verify the invariant.
Case 3: Delete a word in the tree :
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
. 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).
By the way, nullptr would perhap's be be more appropriate than NULL for pointers, even if NULL would work properly as well.
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.