Saturday, November 16, 2024
Google search engine
HomeData Modelling & AIHow to write C functions that modify head pointer of a Linked...

How to write C functions that modify head pointer of a Linked List?

Consider simple representation (without any dummy node) of Linked List. Functions that operate on such Linked lists can be divided into two categories:

1) Functions that do not modify the head pointer: Examples of such functions include, printing a linked list, updating data members of nodes like adding given a value to all nodes, or some other operation that access/update data of nodes 
It is generally easy to decide the prototype of functions of this category. We can always pass the head pointer as an argument and traverse/update the list. For example, the following function that adds x to data members of all nodes.

C




void addXtoList(struct Node *node, int x)
{
    while(node != NULL)
    {
        node->data = node->data + x;
        node = node->next;
    }
}    


2) Functions that modify the head pointer:

Examples include, inserting a node at the beginning (head pointer is always modified in this function), inserting a node at the end (head pointer is modified only when the first node is being inserted), deleting a given node (head pointer is modified when the deleted node is the first node). There may be different ways to update the head pointer in these functions. Let us discuss these ways using the following simple problem:

“Given a linked list, write a function deleteFirst() that deletes the first node of a given linked list. For example, if the list is 1->2->3->4, then it should be modified to 2->3->4”
The algorithm to solve the problem is a simple 3 step process: (a) Store the head pointer (b) change the head pointer to point to the next node (c) delete the previous head node. 

Following are different ways to update the head pointer in deleteFirst() so that the list is updated everywhere.

2.1) Make head pointer global: We can make the head pointer global so that it can be accessed and updated in our function. Following is C code that uses a global head pointer.

C




// global head pointer 
struct Node *head = NULL;
  
// function to delete first node: uses approach 2.1
// See http://ideone.com/ClfQB for complete program and output
void deleteFirst()
{
    if(head != NULL)
    {
       // store the old value of head pointer    
       struct Node *temp = head;
         
       // Change head pointer to point to next node 
       head = head->next; 
  
       // delete memory allocated for the previous head node
       free(temp);
    }
}


See this for a complete running program that uses the above function.

This is not a recommended way as it has many problems like the following: 
a) head is globally accessible, so it can be modified anywhere in your project and may lead to unpredictable results. 
b) If there are multiple linked lists, then multiple global head pointers with different names are needed.

See this to know all reasons why should we avoid global variables in our projects. 

2.2) Return head pointer: We can write deletefirst() in such a way that it returns the modified head pointer. Whoever is using this function, has to use the returned value to update the head node. 

C




// function to delete first node: uses approach 2.2
// See http://ideone.com/P5oLe for complete program and output
struct Node *deleteFirst(struct Node *head)
{
    if(head != NULL)
    {
       // store the old value of head pointer
       struct Node *temp = head;
  
       // Change head pointer to point to next node
       head = head->next;
  
       // delete memory allocated for the previous head node
       free(temp);
    }
  
    return head;
}


See this for complete program and output. 

This approach is much better than the previous 1. There is only one issue with this, if the user misses assigning the returned value to the head, then things become messy. C/C++ compilers allow calling a function without assigning the returned value. 

C




head = deleteFirst(head);  // proper use of deleteFirst()
deleteFirst(head);  // improper use of deleteFirst(), allowed by compiler


2.3) Use Double Pointer: This approach follows the simple C rule: if you want to modify the local variable of one function inside another function, pass a pointer to that variable. So we can pass the pointer to the head pointer to modify the head pointer in our deletefirst() function. 

C




// function to delete first node: uses approach 2.3
// See http://ideone.com/9GwTb for complete program and output
void deleteFirst(struct Node **head_ref)
{
    if(*head_ref != NULL)
    {
       // store the old value of pointer to head pointer
       struct Node *temp = *head_ref;
  
       // Change head pointer to point to next node
       *head_ref = (*head_ref)->next;
  
       // delete memory allocated for the previous head node
       free(temp);
    }
}


See this for complete program and output. 

This approach seems to be the best among all three as there are fewer chances of having problems.

Feeling lost in the world of random DSA topics, wasting time without progress? It’s time for a change! Join our DSA course, where we’ll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!

RELATED ARTICLES

Most Popular

Recent Comments