Search code examples
c++listlinked-listsingly-linked-list

Delete Nodes With The Value 0 In Singly Linked List In C++


I can't for the life of me figure this out I've spent days on this exercise but to no avail.

I'm trying to delete nodes with the value 0 from a singly liked list.

Let's say i have |1|3|0|4|0|5|0|0|. The outcome should be |1|3|4|5|

Here is all the code for reference

#include <iostream>
#include <fstream>

using namespace std;

struct node {
    int data;
    node* next;
};
node* head, *last;
int n;
void creating_list()
{
    node* aux;
    ifstream f("in.txt");
    f >> n;
    for(int i=0;i<n;i++)
    {
        if (head == NULL)
        {
            head = new node;
            f >> head->data;
            head->next = NULL;
            last = head;
        }
        else
        {
            aux = new node;
            f >> aux->data;
            last->next = aux;
            aux->next = NULL;
            last = aux;
            
        }
    }
    
}


void displaying_list() 
{
    node* a;
    a = head;
    if (a == NULL)
        cout << "List is empty! ";
    else
    {
        cout << "Elements of list are: | ";
        while (a)
        {
            cout << a->data<<" | ";
            a = a->next;
        }
    }
}

void delete_first_node()
{
    if (head == NULL)
        cout << "List is empty";
    else
    {
        cout << "Deleting first node\n";
        node* aux;
        aux = head;
        head = head->next;
        delete aux;
    }
}
void delete_last_node()
{
    if (head == NULL)
        cout << "List is empty";
    else
    {
        if (head == last)
        {
            delete head;
            head = last = NULL;

        }
        else
        {
            node* current;
            current = head;
            while (current->next != last)
                current = current->next;
            delete current->next;
            current->next = NULL;
            last = current;
        }
    }
}
void delete_value_0()
{
    node* aux;
    if (head == NULL)
        cout << "List is empty. Can't delete! ";
    else
    
    //  if (head->data == 0)
    //      delete_first_node();
    //  if (last->data == 0)
    //      delete_last_node();
    //  else
        {
            node* a;
            a = head;
            while (a)
                if (a->next->data != 0)
                { 
                    a = a->next;
                    cout << a->data<<" | ";
                }
                else
                    if (a->next != last)
                    {
                        aux = a->next;
                        a->next = a->next->next;
                        delete aux;
                        break;
                    }
        }

    
}

int main()
{
    creating_list();
    displaying_list(); cout <<endl;
    delete_value_0();
    
    return 0;
}

Here is the problem that gives me metal problems I've tried to move one node short of the node that has the 0 value, store the value in another node, aux in this case and delete aux;

I've put comment on those lines because if I don't and the condition it's met it doesn't execute the rest of the code...

If I put break at the end it only shows me the first few numbers until the 0 and then stops short, doesn't move through the full list.

if I don't put break the the program is doesn't stop, it's in an infinite loop, it doesn't exit with code 0

void delete_value_0()
{
    node* aux;
    if (head == NULL)
        cout << "List is empty. Can't delete! ";
    else
    
    //  if (head->data == 0)
    //      delete_first_node();
    //  if (last->data == 0)
    //      delete_last_node();
    //  else
        {
            node* a;
            a = head;
            while (a)
                if (a->next->data != 0)
                { 
                    a = a->next;
                    cout << a->data<<" | ";
                }
                else
                    if (a->next != last)
                    {
                        aux = a->next;
                        a->next = a->next->next;
                        delete aux;
                        break;
                    }
        }

    
}

Honestly I'm at a loss I've spent so much time trying to figure this out, and this should be a very simple exercise. I feel like the answear Is really simple but i don't know what to do anymore, Maybe this is not for me.


Solution

  • This is much simpler than it appears on the first glance. The trick to this task is instead of using a pointer to the current node, a pointer to the pointer to the current node gets used instead. The entire task becomes laughably trivial: only one loop, and one if statement that takes care of all possibilities: the list is empty; the node to delete is the first node in the list; ot the last node in the list; or anywhere in the middle of it.

    void delete_value_0()
    {
        node **p= &head;
    
        while (*p)
        {
            if ((*p)->data == 0)
            {
               node *nextptr=*p;
    
               *p=(*p)->next;
               delete nextptr;
            }
            else
            {
                p= &(*p)->next;
            }
        }
    }