I am having issues with deleting nodes in my doubly linked list, it crashes when I try to delete a node when there is only 1 node in the list. It works well otherwise. Its been driving me crazy because everything I have tried seems to make it worse not better. Here is my delete functions before I started changing them to try and get it to work better.
void doublyLinked::DeleteLast(int value) {
if (first == NULL)
cout <<" ERROR: You cannot delete what is not there. Please Try again! "
<< endl <<endl;
else {
Node* toDelete = last;
last = toDelete -> previous;
last->next = NULL;
delete toDelete;
}// end else
}// end function Delete Last
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void doublyLinked::DeleteFirst(int value) {
if (last == NULL)
cout <<" ERROR: You cannot delete what is not there. Please Try again! "
<< endl <<endl;// end if
else {
Node* toDelete = first;
first->next->previous = NULL;
first = toDelete->next;
delete toDelete;
}//end else
}
If there is only one entry, then first == last. Thus:
last = toDelete -> previous;
last->next = NULL;
is bad because after the first line last is NULL ;
Same with:
first->next->previous = NULL;
in the DeleteFirst()
Assume any next or previous pointer might be NULL and only use it after you've checked. Example:
if ( first->next && first->next->previous ) { first->next->previous= NULL ; }
Also note, your DeteleLast would need to modify first when deleting the last item.
I'd add test, if first == last. If so, delete it, and set both to NULL. Example:
if( first == last ) {
delete first;
first = last = NULL;
return;
}
Related
I can't seem to understand what am I missing, I've spent hours and hours looking at this and everything I tried doesn't work.
My thought process to check if the second node of the list is even, if it is then to link the first and third node and delete the second but it doesn't work... I've been stuck at this for a week.
void delete_even()
{
nod *aux;
if (head == NULL)
{
cout << "List doesn't exist!";
}
else
{
nod *curent;
current = head;
while (curent)
{
if (curent->next->info % 2 == 0)
{
curent = curent->next->next;
curent->next = aux;
delete aux;
break;
}
else
{
curent = curent->next;
}
}
}
}
I don't know what else to do.
There are several things wrong with this code.
Your use of curent->next invokes undefined behavior when curent is pointing at the last node in the list, since next will be NULL in that case. It is are causing you to skip the 1st node in the list.
You never assign aux to point at anything, so calling delete on aux is also undefined behavior.
Even if aux were pointing at a valid node, you are assigning aux to curent->next right before deleting the node that aux is pointing at, thus leaving curent->next pointing at invalid memory, which is also undefined behavior.
If you did manage to remove a node from the list, you are breaking the loop immediately afterwards, so you would be removing only one even number from the list, not removing all even numbers, as your title suggests you want to do.
Try something more like this instead:
void delete_even()
{
if (!head)
cout << "List is empty!";
else
{
nod *curent = head, *prev = NULL;
while (curent)
{
nod *next = curent->next;
if (curent->info % 2 == 0)
{
if (prev)
prev->next = next;
else
head = next;
delete curent;
}
else
{
prev = curent;
}
curent = next;
}
}
}
Alternatively:
void delete_even()
{
if (!head)
cout << "List is empty!";
else
{
nod *curent = head;
nod **prev = &head;
while (curent)
{
if (curent->info % 2 == 0)
{
*prev = curent->next;
delete curent;
}
else
{
prev = &(curent->next);
}
curent = *prev;
}
}
}
I am learning C++ and here I am trying to implement the pop() function of a stack. I am confused about when to delete pointers, and how to delete them correctly. The following code causes a core dump error, however I found a few ways to avoid the core dump. The problem is that I point a pointer to another pointer, and I want to delete both. If I set one to null I can delete both, but if I point one to the other I cannot delete both. What is the appropriate course of action here and why can't I delete both when one points to the other? Also, this is not a doubly linked list, and I am not keeping track of the second node from the top so I must traverse the entire list to delete from the top.
I apologize as it seems that this question gets asked often. There are so many discussions that I cannot sort out one that addresses my problem specifically.
int List::pop() {
int result = -1;
if (head != NULL) {
result = curr->data;
nodePtr delPtr;
if (curr == head) {
delPtr = head;
head = NULL;
}
else {
nodePtr previousNode = head;
while(previousNode->next != curr) {
previousNode = previousNode->next;
}
delPtr = curr;
curr = previousNode;
curr->next = NULL;
previousNode = delPtr; //previousNode = NULL;?????
delete previousNode; //unecessary?????
}
delete delPtr; //Have to delete this one no matter what
}
else {
cout << "The stack is empty" << endl;
}
return result;
}//END pop
You are deleting the curr node twice.
Once in these lines:
previousNode = delPtr; //previousNode = NULL;?????
delete previousNode; //unecessary?????
and once in the line:
delete delPtr; //Have to delete this one no matter what
You can remove the first two lines.
You can remove both these lines:
previousNode = delPtr; //previousNode = NULL;?????
delete previousNode; //unecessary?????
And it will work and be correct.
The error is from deleting the same pointer twice.
previousNode = delPtr is just making a copy of the pointer, there is still only one object.
You don't need to delete twice, you are only removing one item.
Just because a pointer points to something doesn't mean you have to delete it if you change the pointer or it goes out of scope.
In general, you need to match up deletes with news.
In short, you can remove both your commented lines as you already have delPtr set up for deleting.
int List::pop()
{
int result = -1;
if (head != NULL)
{
nodePtr prev = head;
nodePtr curr = head;
while (curr->next != NULL)
{
prev = curr;
curr = curr->next;
}
result = curr->data;
if (head == curr)
{
head = NULL;
}
else
{
prev->next = NULL;
}
delete curr;
}
else
{
cout << "The stack is empty" << endl;
}
return result;
}//END pop
Hi I'm trying to delete a node in a linked list. I am first experimenting on how to delete the head and the tail nodes. The head deletion seems to work, however the tail the deletion does not. When I run the code, the place where the tail used to be is replaced with garbage values. Can anyone figure out why? Many thanks!
void CList :: Remove() {
int data = NULL;
std::cout<<"Enter value you wish to remove ";
std:: cin>> data;
cNode *pMyPointer = m_pHead;
while (pMyPointer != NULL)
{
if (pMyPointer->m_nValue == data) {
std::cout << "Element found";
goto del;
}
else {
pMyPointer = pMyPointer->m_pNext;
}
}
del:
//removing the head
if (pMyPointer == m_pHead)
m_pHead= m_pHead->m_pNext;
//removing the tail
else if (pMyPointer == m_pTail)
m_pTail = m_pTail->m_pPrev;
delete pMyPointer;
}
consider node_1 points to node_2 (just a 2 node case)
Just look at this code
else if (pMyPointer == m_pTail)
m_pTail = m_pTail->m_pPrev;
node_1 points to node_2 . It still points there . once you deleted node_2 , node_1 will still point to node_2 (or garbage once node_2 is deleted) & so you must make sure node_1 points to NULL . ie last but one should point to null .
something like
else if (pMyPointer == m_pTail)
m_pTail->m_pPrev->next=NULL;
m_pTail = m_pTail->m_pPrev;
With this statement
while (pMyPointer != NULL)
Your pointer may be pointing to NULL when it exits the loop and hence it will skip the tail pointer.
Instead try
while (pMyPointer->m_pNext != NULL)
You also need to make the second last node point to NULL.
else if (pMyPointer == m_pTail) {
m_pTail = m_pTail->m_pPrev;
m_pTail->m_pNext = NULL;
}
delete pMyPointer;
Also, instead of goto del, just use break;
Stay one node ahead of the node you want to delete
And what if your tail and head pointer are the same? You don't check for it. Therefore you might be deleting the pointer which you assume to be the Head, which is also a Tail. Plus what if it's Next for a Head or Prev for a Tail?
void CList :: Remove() {
int data = NULL;
std::cout<<"Enter value you wish to remove ";
std:: cin>> data;
cNode *pMyPointer = m_pHead;
while (pMyPointer != NULL)
{
if (pMyPointer->m_nValue == data) {
std::cout << "Element found";
goto del;
}
else {
pMyPointer = pMyPointer->m_pNext;
}
}
del:
//taking care of the neighbors
if (pMyPointer->m_pPrev)
pMyPointer->m_pPrev->m_pNext = pMyPointer->m_pNext;
if (pMyPointer->m_pNext)
pMyPointer->m_pNext->m_pPrev = pMyPointer->m_pPrev;
// removing the head
if (pMyPointer == m_pHead)
m_pHead= m_pHead->m_pNext;
//removing the tail
if (pMyPointer == m_pTail)
m_pTail = m_pTail->m_pPrev;
delete pMyPointer;
}
I'm trying to make a linked list that gets words from the user until the input is blank, and every word is added so the list stays in alphabetical order. However, only the first node is printed. Is there something I'm doing wrong? Here's what I have (minus the header and declarations):
//put in additional nodes until the input is blank
while(in != " "){
cin >> in;
newPtr->data = in;
prevPtr->data = "";
prevPtr->next = NULL;
nextPtr = list;
//shift the prevPtr and nextPtr until newPtr is alphabetically between them
while(!(prevPtr->data<=in && nextPtr->data>in)){
prevPtr = nextPtr;
nextPtr = prevPtr->next;
}
//make newPtr point to the next node
if(nextPtr != NULL){
newPtr->next = nextPtr;
}
//make newPtr the "next" pointer of the previous node, if any
if(prevPtr != NULL){
prevPtr->next = newPtr;
}
//if there's nothing before newPtr, make it the first node
else{
list = newPtr;
}
printList(list);
};
}
I would post this as a comment, because I am afraid I might be missing something, but I can't yet do this, so here goes a non-answer:
What keeps you from using the std::list? You can insert a word, check if it is non-empty, immediately apply a the standard sorting algorithm (It relies on the comparison operators of the sorted objects) and print it. It is fast, your code is short and readable and you don't spend your time reinventing the wheel.
PS: If you want to test for an empty string it should be "", not " " , I think.
I think there is a number of issues here.
For one in the initial iteration what is prevPtr->data pointing at? If it's pointing at nothing or hasn't been allocated to any memory you shouldn't be setting this to anything yet.
Plus you need to allocate memory for newPtr on every iteration, otherwise you are just writing over the memory location of where it is pointing to last from the in the list.
Second lets assume that prevPtr is pointing to something, on the second iteration (or more) of this while loop prevPtr has been moved farther down the list (prevPtr = nextPtr) which would cause prevPtr->data = " " to erase any data in that element. So you could be printing the first node plus a bunch of spaces afterwards.
Third you should check if list is NULL first in your loop, because if loop is NULL, nextPtr->data would be pointing at junk which is not good. This NULL check on list could be your corner case of the first element.
Try something like this, I didn't have time to test it but it should get going in the right direction:
Node *list = NULL;
while(in != " "){
cin >> in;
Node *newPtr = new Node();
newPtr->data = in;
newPtr->next = NULL;
prevPtr = list;
nextPtr = list;
// Do we have an empty list
if(list != NULL)
{
// Corner Case: First on the list
if(newPtr->data <= prevPtr->data)
{
list = newPtr;
newPtr->next = prevPtr;
}
else
{
// CASE: Somewhere between the first and the list
while(nextPtr->next != NULL)
{
nextPtr = nextPtr->next;
if(newPtr->data >= prevPtr->data && newPtr->data <= nextPtr->data)
{
prevPtr->next = newPtr;
newPtr->next = nextPtr;
break;
}
prevPtr = prevPtr->next;
}
// Corner Case: end of list
if(nextPtr->next == NULL)
{
nextPtr->next = newPtr;
}
}
}
else
{
// Corner Case: We had an empty list
list = newPtr;
}
printList(list);
I have a linked list with a c-style ctor and dtor.
I just got too frustrated when this if statement decided not to test true, putting me in
an infinite loop. I dont understand why it will never test true.
I am trying to delete a node (the address of a class object) from my LinkedList.
Maybe someone could help me out?
Node *Current = first_; // I want this to be my only Node Ptr Varaible Declaration.
if ( NULL == first_ )
std::cout << "Cannot delete from an empty list: \n";
while ( Current != NULL )
{
if ( first_->data_ == node->data_ )
{
//check to see if we are deleteing the head.
first_ = first_->next_;
--listLen_;
delete Current;
std::cout << "Head Deleted!\n";
}
if ( Current->data_ == node->data_ ) // FOR SOME REASON this is never true?
{
--listLen_;
node->data_ = NULL;
Current = Current->next_;
node->data_ = Current;
}
else // we must not of found it. // else should match previous i
{
Current->prev_ = Current;// since we are not deleting the first node we are OK here.
Current = first_->next_;
if ( Current->next_ == NULL ) // see if we are at the end of the list.
{
first_ = NULL;
last_ = Current->prev_;
}
}
}
return;
This should really be rewritten, since it has too many problems...also why not use a STL container? I assume this is a homework question.
The answer to the infinite loop is the else case that increments to the next node:
Current = first_->next_;
This will make you loop forever if the data is not found in in the first two nodes...since you will set the next test to the first's next node always and it will never set the current to NULL provided there are more than 2 nodes in the list.
Keep your loops small, it easier to figure out what went wrong. Assuming your data compare makes sense, look at this the following:
curr = first_;
while( curr && (curr->data_ != node->data_) ) {
curr = curr->next_;
}
if (!curr) return // didnt find it, nothing to remove
if ( curr == first_ )
first_ = curr->next_
else
curr->prev_->next_ = curr->next_
curr->next_->prev_ = curr->prev_ // always fix next's prev
delete curr
I'm not entirely sure what you're trying to accomplish, but I'm certain you're doing it wrong. If you're merely trying to remove an element from a doubly-linked list that matches node->data_, it's as easy as this:
Node *Current = first_;
while (Current != NULL)
{
if (Current->data_ == node->_data)
{
//If Current isn't the head of the list, set prev to next
if (Current != first_)
Current->prev_->next_ = Current->next_
else
{
first_ = Current->next_;
if (first_ != NULL)
first_->prev_ = NULL;
}
//If Current isn't the tail of the list, set next to prev
if (Current->next_ != NULL)
Current->next_->prev_ = Current->prev_
else if (Current->prev_ != NULL)
Current->prev_->next_ = NULL;
delete Current;
Current = NULL;
}
else
{
Current = Current->next_;
}
}
return;
You don't show where node comes from or how data_ is defined, but if it is a pointer type, you probably need to compare the contents, not the addresses.
Assuming that data_ is a pointer to something and what it points to has operator== defined or is a built in type and it has the value you are looking for then you can do this instead:
if ( *Current->data_ == *node->data_ )
if first_->data_ == node->data_ ever evaluates to true then the second if statement will always evaluates to true then the second if condition will always evaluate to false Current->data_ == node->data_ because on the first iteration first_ == Current and you delete Current without ever updating it
To delete a node from a linked list you seem to be doing way too much work.
Not really an answer here for the actual question but a suggestion.I would never iterate through a linked list to delete an entry in the list. Each entry should have a valid next and previous pointer and when you go to delete an entry from the list you just make the previous record point to the next one and vice versa to remove yourself from the list. An empty list should have a head record and a tail record that just point to each other and all valid entries are inserted in between.
Delete a node with value passed.
void deleteBegin()
{
Node* temp =Head;
if(temp==NULL)
return;
Head=Head->next;
free(temp);
}
void deleteMiddle(int _data)
{
Node* curr = Head;
Node* prev = Head;
if(curr==NULL)
return;
if(curr->next==NULL)
{
deleteBegin();
return;
}
while(curr->next!=NULL && curr->data!=_data)
{
prev=curr;
curr=curr->next;
}
if(curr->data == _data)
{
if(prev==curr)
{
deleteBegin();
return;
}
prev->next = curr->next;
free(curr);
}
else
{
cout<<"Element Not Found\n";
return;
}
}