L-13 MCS 360 Wednesday 12 February 2003

In this lecture we use linked lists to implement priority queues.

0. The Abstract Data Type of a priority queue

abstract typedef <<elements>> priority_queue;
/* a priority queue is a sequence of elements */

abstract int length ( priority_queue q );
postcondition: returns number of elements in q */

abstract int delete_element ( priority_queue q, elements e );
precondition: length(q) > 0;
postcondition: smallest element is removed from priority queue q,
               returns -1 if length(q) == 0, returns 0 otherwise;

abstract void insert_element ( priority_queue q, elements e );
postcondition: element e is inserted to the priority queue q; 

1. the file priority_queue.h

/* L-13 MCS 360 Wednesday 12 February 2003
 *   Declaration of a priority queue as a list. 
 *   Compared to the ADT we had to change the declaration of 
 *   those functions which modify the priority queue,
 *   because call by reference in C simply copies
 *   the value of the pointer to the argument of the function.
 *   Call-by-reference in C is call-by-value on addresses. */

typedef struct
{
   int   number;    /* number of job */
   float duration;  /* duration of job */
} job;

typedef struct list priority_queue;
/* a priority queue is a list of jobs */

struct list
{
   job item;              /* first job in list */
   priority_queue *next;  /* points to next job */
};

int length ( priority_queue *q );
/* postcondition: returns number of elements in q */

priority_queue *delete_job ( priority_queue *q, job *j, int *flag );
/* precondition: length(q) > 0;
 * postcondition: smallest job is removed from priority queue q,
 *                if empty(q), *flag == -1, otherwise *flag == 0; */

priority_queue *insert_job ( priority_queue *q, job j );
/* postcondition: job j is inserted to the priority queue q; */

void write_jobs ( priority_queue *q );
/* postcondition: writes all jobs in the queue to the screen; */

2. the file priority_queue.c

/* L-13 MCS 360 Wednesday 12 February 2003
 *   implementation of the operations in the priority queue */

#include <stdlib.h>
#include "priority_queue.h"

int length ( priority_queue *q )
{
   if (q == NULL)
      return 0;
   else
      return 1 + length(q->next);
}

priority_queue *delete_job ( priority_queue *q, job *j, int *flag )
{
   if (q == NULL) 
   {
      *flag = -1;
      return q;
   }
   else
   {
      priority_queue *nq;

      *flag = 0;
      *j = q->item;
      nq = q->next;
      free(q);
 
      return nq;
   }
   
}

priority_queue *insert_job ( priority_queue *q, job j )
{
   priority_queue *nq;

   nq = (priority_queue*) calloc(1,sizeof(priority_queue));
   nq->item = j;

   if (q == NULL)
   {
      nq->next = NULL;
      return nq;
   }
   else if (j.duration < q->item.duration)
   {
      nq->next = q;
      return nq;
   }
   else
   {
      priority_queue *previous = q;
      priority_queue *current = q->next;

      while (current != NULL)
      {
         if (j.duration < current->item.duration) break;
         previous = current;
         current = current->next;
      }
      previous->next = nq;
      nq->next = current;

      return q;
   }
}

void write_jobs ( priority_queue *q )
{
   if (q != NULL)
   {
      job j = q->item;
      printf("  job %d has duration %f\n", j.number, j.duration);
      write_jobs(q->next);
   }
} 

3. the file use_priority_queue.c

/* L-13 MCS 360 Wednesday 12 February 2003
 *   Simple interactive program to test the priority queue. */

#include <stdio.h>
#include "priority_queue.h"

int main ( void )
{
   priority_queue *q;
   char action;
   job j;
   int jobnb = 0;
   int check;

   q = NULL;

   do
   {
      printf("\nNumber of jobs in priority queue : %d.\n",length(q));
      write_jobs(q);

      printf("\nChoose one of the following :\n");
      printf("  0. leave this program\n");
      printf("  1. insert job to the queue\n");
      printf("  2. delete job from the queue\n");
      printf("Make your choice : ");
      scanf(" %c", &action);

      switch(action)
      {
         case '0': printf("\n  Bye bye.\n\n");
                   break;
         case '1': j.number = jobnb++;
		   printf("\n  Give duration : ");
                   scanf("%f", &j.duration);
                   q = insert_job(q,j);
                   break;
         case '2': q = delete_job(q,&j,&check);
                   if (check == 0)
                      printf("\n  Deleted job %d with duration %f.\n",
                             j.number, j.duration);
                   else
                      printf("\n  There were no jobs to delete.\n");
                   break;
         default:  printf("\n  Invalid choice, try again...\n");
      }
   }
   while (action != '0');

   return 0;
}