Removing an item at the front of the linked list

  • Example: the linked list before the removal of the String item "to":

  • The linked list after the removal of "to":

    Note:

    • The removeFirst() will also return the location (reference) of the new first list element of the linked list

Garbage...

  • Notice the final state of the removeFirst( ) method:

  • In reality, the final state is as follows:

  • Notice that the first node has become garbage (i.e.: inaccessible)

    • Unlike Java, the C runtime system do not have a garbage collector

    • We must de-allocate (= unreserve) a deleted node in C

Review + Application: de-allocating deleted nodes

  • Suppose we have previously allocated memory for an object using malloc( ):

     #include <stdlib.h>  // malloc( ) is declared in stdlib.h
    
     struct Node  *p;
    
     // Allocate (= reserve) memory for a List object
     p = malloc( sizeof( struct Node ) ); 

  • To de-allocate (= unreserve) the previously allocated memory:

     #include <stdlib.h>  // free( ) is declared in stdlib.h
    
     free( p ) ; 

  • Therefore:   we must use free( ) to de-allocate the deleted node:

Implementation of removeFirst()

The implementation of the removeFirst() method:

  • Let's write the removeFirst() method:

       // Removes the first element (node) from the list.
       // Returns the first element of the new list
       struct Node *removeFirst(struct Node *h)
       {
          if ( h == NULL )            // Check if list is empty
          {
             return NULL;
          }
    
          struct Node *ret = h->next; // Return value
          free(h);                    // De-allocate the delete node
    
          return ret;                 // Return new first node
       }   

Implementation of removeFirst()

The implementation of the removeFirst() method:

  • Save the return value in ret:

       // Removes the first element (node) from the list.
       // Returns the first element of the new list
       struct Node *removeFirst(struct Node *h)
       {
          if ( h == NULL )            // Check if list is empty
          {
             return NULL;
          }
    
          struct Node *ret = h->next; // Return value
          free(h);                    // De-allocate the delete node
    
          return ret;                 // Return new first node
       }  

Implementation of removeFirst()

The implementation of the removeFirst() method:

  • De-allocate the deleted list element:

       // Removes the first element (node) from the list.
       // Returns the first element of the new list
       struct Node *removeFirst(struct Node *h)
       {
          if ( h == NULL )            // Check if list is empty
          {
             return NULL;
          }
    
          struct Node *ret = h->next; // Return value
          free(h);                    // De-allocate the delete node
    
          return ret;                 // Return new first node
       } 

Implementation of removeFirst()

The implementation of the removeFirst() method:

  • Return the saved return value:

       // Removes the first element (node) from the list.
       // Returns the first element of the new list
       struct Node *removeFirst(struct Node *h)
       {
          if ( h == NULL )            // Check if list is empty
          {
             return NULL;
          }
    
          struct Node *ret = h->next; // Return value
          free(h);                    // De-allocate the delete node
    
          return ret;                 // Return new first node
       }

Implementation of removeFirst()

Check if algorithm is correct for edge case(s):

  • Edge case: empty list (i.e.: h == NULL)

       // Removes the first element (node) from the list.
       // Returns the first element of the new list
       struct Node *removeFirst(struct Node *h)
       {
          if ( h == NULL )            // Check if list is empty
          {
             return NULL;
          }
    
          struct Node *ret = h->next; // ==> NULL->next 
          free(h);                    // This will cause a crash !  
    
          return ret;                 
       } 

Implementation of removeFirst()

Handle the empty list edge case:

  • The removeFirst( ) method:

       // Removes the first element (node) from the list.
       // Returns the first element of the new list
       struct Node *removeFirst(struct Node *h)
       {
          if ( h == NULL )            // Check if list is empty
          {
             return NULL;     // Handle empty list
          }
    
          struct Node *ret = h->next; // Using a null pointer 
          free(h);                    // This will cause a crash !  
    
          return ret;                 
       } 

DEMO: demo/C/Linked-list/removeFirst.c

What is happen if you do not of de-allocate the deleted list element ?

  • The effect of not de-allocating (= unreserve) garbage:

    • Garbage that is not de-allocated will continue to use memory space

    • When a program continue to generate garbage, the available memory will eventually become exhausted

    • When this happens, the memory allocation malloc( ) will crash

  • Experiment: run this demo with a modified removeFirst()

       // Removes the first element (node) from the list.
       // Returns the first element of the new list
       struct Node *removeFirst(struct Node *h)
       {
          if ( h == NULL )            // Check if list is empty
          {
             return NULL;
          }
    
          struct Node *ret = h->next;  
          free(h);                    // Skip de-allocation...  
    
          return ret;                 
       } 

DEMO: demo/C/Linked-list/garbage.c + run-garbage