Reputation: 31
This is my deletion code. The problem is that when i delete something from the tail or an nth node it works perfectly fine but whenever i delete something from the head it crashes. What check should i make in order to avoid the crash?
void List::Delete(int data) {
// Create a temp pointer
Node *tmp = head;
// No nodes
if ( tmp == NULL )
return;
// Last node of the list
if ( tmp->Next() == NULL ) {
delete tmp;
head = NULL;
}
else {
// Parse through the nodes
Node *prev;
do {
if ( tmp->Data() == data ) break;
prev = tmp;
tmp = tmp->Next();
} while ( tmp != NULL );
// Adjust the pointers
prev->SetNext(tmp->Next());
// Delete the current node
delete tmp;
}
}
Upvotes: 0
Views: 61
Reputation: 1463
There are more than one problems with this code.
if ( tmp->Next() == NULL )
this check does not mean "Last node of the list" infact it means that there is only one node in the list since the code below only runs if there are at least two nodes you need to handle this case here.tmp->Data() == data
check is needed in addition to the above check to make sure that the only node in the list is also the node we want to delete before deleting it.Node *prev = NULL;
this pointer should be initialized so that we can check for NULL
later to see if it is the head that needs to be deleted.if ( tmp->Data() == data )
before the break;
is applied, otherwise you will have no way to know if the loop ended naturally or was broken, to decide whether the node was found or not.Here is the corrected code:
void List::Delete(int data) {
// Create a temp pointer
Node *tmp = head;
// No nodes
if ( tmp == NULL )
return;
// it is the only node in the list
if ( tmp->Next() == NULL && tmp->Data() == data ) {
delete tmp;
head = NULL;
}
else {
// Parse through the nodes
Node *prev = NULL;
do {
if ( tmp->Data() == data ){
if( prev == NULL ) // this is the head case
head = head->Next();
else // Adjust the pointers
prev->SetNext(tmp->Next());
// Delete the current node
delete tmp;
break;
}
prev = tmp;
tmp = tmp->Next();
} while ( tmp != NULL );
}
}
Note: The tail case works fine without any alterations in the code because, the only difference that this case creates, is that tmp->Next()
for that case would be NULL
which is exactly what we want for the new tail in prev->SetNext(tmp->Next());
i.e. set its Next
to NULL
.
Upvotes: 0
Reputation: 4343
If the node to delete is the head node, then this is what happens:
You declare Node *prev
. Notice that it is uninitialised. Then you enter the do while
loop, but break at the first if condition because tmp->Data() == data
. So you exit the do while loop without executing the next statement, which would initialise prev
. Now out of the loop, the next statement accesses the SetNext
field of prev
, whereas previous is unitialised. This is undefined behavior, and anything can happen; crashing is one such thing.
The way to avoid this is to add a check for whether prev
is unitialised, or 'tmp' is the head node. In this case, you should delete the head, and return the node after head. Since your function has a void
signature, you should delete the head node, and make the head pointer reference the node after head.
Upvotes: 1