Search code examples
cstructlinked-listsingly-linked-listfunction-definition

Loop for Linked Lists


I really like this implementation of code but I don't want it to be hardcoded so can someone help me to make a loop for list = new_node(1); and so forth.

#include <stdlib.h>
#include <stdio.h>

typedef struct node {
    int number;
    struct node *next;
} node;

node *new_node(int number)
{
    node *n = malloc(sizeof(*n));
    if (n == NULL)
    {
        perror("new_node");
        exit(1);
    }
    n->number = number;
    n->next = NULL;
    return n;
}

int main(void) {
    node *list;

    list = new_node(1);
    list->next = new_node(2);
    list->next->next = new_node(3);
    list->next->next->next = new_node(4);

    for (node *tmp = list; tmp != NULL; tmp = tmp->next)
    {
        printf("%i\n", tmp->number);
    }

    while (list != NULL) {
        node *tmp = list->next;
        free(list);
        list = tmp;
    }
    return 0;
}

Solution

  • As you are trying to add new nodes to the tail of the list then in this case it will be reasonable to define a two-sided singly-linked list.

    For example

    typedef struct node 
    {
        int number;
        struct node *next;
    } node;
    
    typedef struct list
    {
        struct node *head;
        struct node *tail;
    } list;
    

    In main you can declare a list like

    list lst = { .head = NULL, .tail = NULL };
    

    A function that appends nodes to the tail of the list can look like

    node * new_node( int number )
    {
        node *n = malloc( sizeof( *n ) );
    
        if ( n != NULL )
        {
            n->number = number;
            n->next = NULL;
        }
    
        return n;
    }
    
    int push_back( list *lst, int number )
    {
        node *n = new_node( number );
        int success = n != NULL;
    
        if ( success )
        {
            if ( lst->tail == NULL )
            {
                lst->head = n;
            }
            else
            {
                lst->tail->next = n;
            }
    
            lst->tail = n;
        }
    
        return success;
    } 
    

    And in main the function is called like

    push_back( &lst, 1 );
    

    or

    if ( !push_back( &lst, 1 ) )
    {
        puts( "Error: there is no enough memory." );
    }
    

    Here is a demonstration program.

    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct node 
    {
        int number;
        struct node *next;
    } node;
    
    typedef struct list
    {
        struct node *head;
        struct node *tail;
    } list;
    
    node * new_node( int number )
    {
        node *n = malloc( sizeof( *n ) );
    
        if ( n != NULL )
        {
            n->number = number;
            n->next = NULL;
        }
    
        return n;
    }
    
    int push_back( list *lst, int number )
    {
        node *n = new_node( number );
        int success = n != NULL;
    
        if ( success )
        {
            if ( lst->tail == NULL )
            {
                lst->head = n;
            }
            else
            {
                lst->tail->next = n;
            }
    
            lst->tail = n;
        }
    
        return success;
    } 
    
    void display( const list *lst )
    {
        for ( const node *current = lst->head; current != NULL; current = current->next )
        {
            printf( "%d -> ", current->number );
        }
    
        puts( "null" );
    }
    
    int main( void )
    {
        list lst = { .head = NULL, .tail = NULL };
        enum { N = 10 };
    
        for ( int i = 0; i < N; i++ )
        {
            push_back( &lst, i );
        }
    
        display( &lst );
    }
    

    The program output is

    0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
    

    You will need to write yourself some other function as for example a function that will free all the memory allocated for the list.