Review:   deleting the element at the head of a linked list

  • Delete the list element at the head (= start) of the linked list at h and return the new list

    Input:

  • Output:

Review:   delete at head algorithm in Java

  • In CS171, you learned the following delete at head algorithm in Java:

    class List // Class  definition included to use 1 program file
    {
       int value;
       List next;
    }
    
    public class insert
    {
       public static List delete (List h)
       {
          if (h != null)
             return h.next;  // Return new list that starts at 2nd elem
          else
             return null;
       }
    
       ... // Other code omitted for brevity
    }

To write a C function, you need to express the algorithm (a concept !) with C syntax

Review:   delete at head algorithm in Java

  • The class definition becomes a struct definition in C:

    struct List // Struct definition included to use 1 program file
    {
       int value;
       struct List *next;  // Reference variable
    }
    
    public class insert
    {
       public static List delete (List h)
       {
          if (h != null)
             return h.next;  // Return new list that starts at 2nd elem
          else
             return null;
       }
    
       ... // Other code omitted for brevity
    }

Next:   public class ....

Review:   delete at head algorithm in Java

  • There is no class construct in C:

    struct List // Struct definition included to use 1 program file
    {
       int value;
       struct List *next;  // Reference variable
    }
    
    
    
    public static List delete (List h)
    {
        if (h != null)
            return h.next; // Return new list that starts at 2nd elem
        else
            return null;
    }
    
    ... // Other code omitted for brevity
    
    

Next:   the parameters and return value

Review:   delete at head algorithm in Java

  • The data type of the parameters and return value are both: struct List *

    struct List // Struct definition included to use 1 program file
    {
       int value;
       struct List *next;  // Reference variable
    }
    
    
    
    struct List *delete (struct List *h)
    {
        if (h != null)
            return h.next; // Return new list that starts at 2nd elem
        else
            return null;
    }
    
    ... // Other code omitted for brevity
    
    

Next:   the expression h.next

Review:   delete at head algorithm in Java

  • The Java expression h.next expressed in C is (*h).next or h->next:

    struct List // Struct definition included to use 1 program file
    {
       int value;
       struct List *next;  // Reference variable
    }
    
    
    
    struct List *delete (struct List *h)
    {
        if (h != null)
            return h->next; // Return new list that starts at 2nd elem
        else
            return null;
    }
    
    ... // Other code omitted for brevity
    
    

Next:   the expression null

Review:   delete at head algorithm in Java

  • C uses NULL for the null value in Java:

    struct List // Struct definition included to use 1 program file
    {
       int value;
       struct List *next;  // Reference variable
    }
    
    
    
    struct List *delete (struct List *h)
    {
        if (h != NULL)
            return h->next; // Return new list that starts at 2nd elem
        else
            return NULL;
    }
    
    ... // Other code omitted for brevity
    
    

Done.... wait.... done ?

The delete at head program in Java

class List  // Class included to make 1 program file
{
   int value;
   List next;
}

public class delete 
{
   /* ====================================================
      delete(h): delete the first elem from the list h
                 return new list
      ==================================================== */
   public static List delete (List h)
   {
      if ( h != null )
         return (h.next); // Return new list that starts at h.next
      else
         return null;
   }

   public static void main(String[] args)
   {
      List head = null;

      // Insert 10 elements
      for (int i = 1; i <= 10; i++)
      {
         List e = new List();
         e.value = i;
         head = insert(head, e);       // Insert i at head
         print(head);
      }

      // Delete 10 elements
      for (int i = 1; i <= 10; i++)
      {
         head = delete(head);          // Delete at head
         print(head);
      }
   }

   public static List insert (List h, List e)
   {
      e.next = h;
      return e;         // Return new list that starts at e
   }

   // Print the list
   public static void print(List h)
   {
      while (h != null)
      {
         System.out.printf("%d ", h.value);
         h = h.next;
      }
      System.out.printf("\n\n");
   }
} 

DEMO: demo/C/Linked-list/delete.java

The delete at head program in C

I will "convert" the program in class as a demo

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

struct List
{
   int          value;
   struct List *next;
};

void print(struct List *h);     // Declaration
struct List *insert (struct List *h, struct List *e);

/* ====================================================
   delete(h): delete the first elem from the list h
              return new list
   ==================================================== */
struct List *delete (struct List *h)
{
   if ( h != NULL)
      return h->next; 
   else
      return NULL;
}

int main(int argc, char *argv[])
{
  struct List *head = NULL;

   // Insert
   for (int i = 1; i <= 10; i++)
   {
       struct List *e = malloc( sizeof(struct List) ) ;
       e->value = i;
       head = insert(head, e);       // Insert i at head
       print(head);
   }

   // Delete
   for (int i = 1; i <= 10; i++)
   {
       head = delete(head);          // Delete at head
       print(head);
   }
}

// Insert at head
struct List *insert (struct List *h, struct List *e)
{
    e->next = h;
    return e;     // Return new list that starts at e
}

// Print the list
void print(struct List *h)
{
   while (h != NULL)
   {
      printf("%d ", h->value);
      h = h->next;
   }
   printf("\n\n");
}  

The out-of-memory error when you generate too much garbage

Now run this modified program using (ulimit -v 50000; a.out > err)

int main(int argc, char *argv[])
{
   struct List *head = NULL;
   int c = 0;

   while(1)  // Infinite loop...
   {
      printf("%d\n", ++c);  // Keep a count

      // Insert
      for (int i = 1; i <= 10; i++)
      {
          struct List *e = malloc( sizeof(struct List) ) ;
          e->value = i;
          head = insert(head, e);       // Insert i at head
          print(head);
      }

      // Delete
      for (int i = 1; i <= 10; i++)
      {
          head = delete(head);          // Delete at head
          print(head);
      }
   }
}  

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

The problem with the delete( ) function

  • When you delete a list element from a list:

  • The deleted element becomes inaccessible (a.k.a.: garbage):

  • In Java, a garbage collection mechanism will reclaim the innaccessible memory

  • In C, too much garbage will cause a out-of-(free)-memory error !

The correct way to delete a list element in C

  • The original delete( ) function is:

    struct List *delete (struct List *h)
    {
        if (h != NULL)
        {
            // Delete the element at h
    
    
    
    
            return h->next; 
        }
        else
            return NULL;
    } 

  • The element at h needs to be de-allocated ("unreserved")

The correct way to delete a list element in C

  • We must de-allocate the head list element with free(h):

    struct List *delete (struct List *h)
    {
        if (h != NULL)
        {
            // Delete the element at h
    
    
            free(h);   // De-allocate the deleted element
    
            return h->next; 
        }
        else
            return NULL;
    } 

  • However:   free(h) may affect the variable h->next (= the return value !)

The correct way to delete a list element in C

  • We save the return value first:

    struct List *delete (struct List *h)
    {
        if (h != NULL)
        {
            // Delete the element at h
    	struct List *retVal = h->next;
    
            free(h);   // De-allocate the deleted element
    
            return retVal; 
        }
        else
            return NULL;
    } 

  • This version of delete() will not generate garbage !

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