Search code examples
cpointerspass-by-referencesingly-linked-listfunction-definition

Why should we use double pointer for adding node in front/back, but not in the middle?


I have this code which creates new node at the very front:

void push(struct Node** head_ref, int new_data)
{
    struct Node* new_node = (struct Node*) malloc(sizeof(struct Node));
   
    new_node->data  = new_data;
   
    new_node->next = (*head_ref);
   
    (*head_ref)    = new_node;
}

And I have this code which creates a new node after another one:

void insertAfter(struct Node* prev_node, int new_data) 
{ 
    if (prev_node == NULL) 
    { 
       printf("the given previous node cannot be NULL");     
       return; 
    } 
          
    struct Node* new_node =(struct Node*) malloc(sizeof(struct Node)); 
  
    new_node->data = new_data; 
  
    new_node->next = prev_node->next; 
  
    prev_node->next = new_node; 
}

I understand that if we pass a single pointer a.k.a. head in the first case, the changes will take effect only in the push function, rather than the whole program. That's why we use reference to head to change what it points to.

In the second case, though, we pass a single pointer. I just don't understand why when we are not using reference to the previous node, the code will still work even though we are changing next to point to the new node.

Shouldn't these changes remain only in the insertAfter function?


Solution

  • In the first function

    void push(struct Node** head_ref, int new_data)
    {
        struct Node* new_node = (struct Node*) malloc(sizeof(struct Node));
       
        new_node->data  = new_data;
       
        new_node->next = (*head_ref);
       
        (*head_ref)    = new_node;
    }
    

    there is changed the pointer itself to the head node. So the function needs to deal with the original pointer not with a copy of its value.

    So you need to pass the pointer to th head node by reference.

    In C passing by reference means passing an object indirectly through a pointer to it. In this case dereferencing the pointer like in this statement of the function

        (*head_ref)    = new_node;
    

    the function has a direct access to the original passed object.

    In the second function

    void insertAfter(struct Node* prev_node, int new_data) 
    { 
        if (prev_node == NULL) 
        { 
           printf("the given previous node cannot be NULL");     
           return; 
        } 
              
        struct Node* new_node =(struct Node*) malloc(sizeof(struct Node)); 
      
        new_node->data = new_data; 
      
        new_node->next = prev_node->next; 
      
        prev_node->next = new_node; 
    }
    

    the pointer prev_node itself is not being changed. It is the node pointed to by the pointer that is being changed. So there is no need to pass the original pointer to the function by reference. On the other hand the node pointed to by the pointer prev_node is passed by reference due to the pointer. And using the pointer you can change data members of the pointed node.