Search code examples
cdata-structureslinked-listinsertion

Linked List Insertion in C using double pointer


Hi I'm a newbie learning Linked List, I created this sample program ,but it is not populating all the list, only last two are getting populated (or these overwriting the first linked elements)

Can someone please help me what is causing the issue ?

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

struct node {
    int data;
    struct node *link;
};  

void appendNode(int data, struct node **ptr) {

    struct node *newnode = (struct node*)malloc(sizeof(struct node));

    newnode->data = data;
    newnode->link = NULL;

    if(*ptr == NULL) {
         *ptr = newnode;
    } else {
        while((*ptr)->link != NULL ) {
            *ptr = (*ptr)->link;
        }
        (*ptr)->link = newnode;
    }

}

void printList(struct node *node) 
{ 
  while (node != NULL) 
  { 
     printf(" %d ", node->data); 
     node = node->link; 
  } 
} 

int main() {

    struct node *head = NULL ;

    appendNode(23,&head);
    appendNode(45,&head);
    appendNode(32,&head);
    appendNode(11,&head);
    appendNode(98,&head);
    printList(head);

}

Ir prints

 11  98 

What is causing the issue here ?


Solution

  • Your problem is that you are iterating with the pointer itself in appendNode[1]. This is changing the list address every time you assign something to *ptr, e.g.

         *ptr = newnode;
         ...
            *ptr = (*ptr)->link;
    

    Each time *ptr is assigned the list address is changed (both as seen in appendNode and in main())

    Your list operations are correct, all you need to do is use a temporary pointer to iterate over the list (iter below)

    void appendNode (int data, struct node **ptr) {
    
        struct node *newnode = malloc (sizeof *newnode),
            *iter = *ptr;
    
        if (!newnode) { /* VALIDATE every allocation */
            perror ("malloc-newnode");
            exit (EXIT_FAILURE);
        }
    
        newnode->data = data;
        newnode->link = NULL;
    
        if (iter == NULL) {
            *ptr = newnode;
        }
        else {
            while (iter->link != NULL) {
                iter = iter->link;
            }
            iter->link = newnode;
        }
    }
    

    (note the use of the dereferenced pointer used with sizeof to set the type-size. If you use the dereferenced pointer to set the size, you eliminate any mistake in setting the actual type needed. Also, if you allocate -- you must validate -- every time)

    With that change (and the following change to printList)

    void printList (struct node *node) 
    { 
        while (node != NULL) 
        { 
            printf(" %d ", node->data); 
            node = node->link; 
        }
        putchar ('\n');     /* tidy up with newline */
    } 
    

    Your list works just fine, e.g.

    Example Use/Output

    $ ./bin/lllast2
     23  45  32  11  98
    

    footnotes:

    1. While not an error, C generally avoids the use of camelCase or MixedCase variable names in favor of all lower-case while reserving upper-case names for use with macros and constants. It is a matter of style -- so it is completely up to you, but failing to follow it can lead to the wrong first impression in some circles.