Lecture 18:  Dynamic Memory Allocation –Queue

 

Objectives of this lecture

q       Learn how queue may be implemented using dynamic memory allocation

q       Do the implementation such that it is completely compatible with the array implementation.

 

Queue Implementation

q       This has the same advantage as dynamic implementation of stack –No too much or too little memory problem.  The queue grows and shrinks as elements are added and removed.

q       In addition, there is no need to think of a queue as a circular structure.  Dynamic queue is strictly linear.

q       In this implementation, we think of a queue as a sequence of nodes with each node pointing to the next except the last which points to NULL.  We also have two pointers, front and rear which points to the front and rear nodes respectively.

q       The following diagram illustrates this idea.

q       Initially, both front and rear are set to NULL, indicating that the queue is empty.

 

q       To add an element we proceed as follows:

Ø      We obtain a node using malloc()

Ø      Add new_item to the item field of the new node

Ø      Set the next field of the new node to NULL

Ø      Connect the new node to current rear node  

Ø      Re-direct the rear pointer to point to the new node. 

Ø      If this is the first node being added, front pointer is also re-directed to point to it.

 

q       To remove an item front the front:

Ø      First we return the item field of the current front node

Ø      Use a temporary pointer to point to the current front node

Ø      Sets the next field of the current front node to be the new front and then

Ø      free the node being pointed by the temporary pointer. 

Ø      If the queue is now empty as a result of the removal, rear is also set to NULL

 

q       Like dynamic implementation of stack, destroying a dynamic queue involves returning all the nodes back to the system using the free() function.

q       Also, the function full_queue is only necessary for compatibility purpose. 

q       The implementation now follows:

 

User Interface:

typedef char ITEM_TYPE;

typedef struct node_type { ITEM_TYPE item;

                                struct node_type *next;

                              } NODE_TYPE;

typedef NODE_TYPE *NODE_PTR;

typedef struct { NODE_PTR front;

                    NODE_PTR rear;

                 } Q_TYPE;

typedef enum {FALSE, TRUE} BOOLEAN;

 

void create_queue(Q_TYPE *queue);

void destroy_queue(Q_TYPE *queue);

BOOLEAN empty_queue(Q_TYPE *queue);

BOOLEAN full_queue(Q_TYPE *queue);

void enqueue(Q_TYPE *queue, ITEM_TYPE new_item);

void dequeue(Q_TYPE *queue, ITEM_TYPE *front_item);

 

Implementation Details:

#include <stdlib.h>

#include "c:\ics201\queue2.h"

 

/* initialize queue by setting both front and rear to NULL */

void create_queue(Q_TYPE *queue)

{  queue->front=NULL;

   queue->rear=NULL;

}

/* resets queue to empty & returns the nodes being occupied by the elements of the queue to the system */

void destroy_queue(Q_TYPE *queue)

{  NODE_PTR temp_ptr;

 

   while ( empty_queue(queue) == FALSE)

   {  temp_ptr=queue->front;

      queue->front=queue->front->next;

      free(temp_ptr);

   }

   queue->rear = NULL;

}

 

/* returns true if front is NULL */

BOOLEAN empty_queue(Q_TYPE *queue)

{  if (queue->front == NULL)

      return TRUE;

   else

      return FALSE;

}

 

/* always returns false */

BOOLEAN full_queue(Q_TYPE *queue)

{  return FALSE;

}

 

/* adds an element to the rear of the queue */

void enqueue(Q_TYPE *queue, ITEM_TYPE new_item)

{  NODE_PTR new_node;

 

   new_node=(NODE_PTR) malloc(sizeof(NODE_TYPE));

   new_node->item=new_item;

   new_node->next=NULL;

   if (empty_queue(queue)==TRUE)

      queue->front=new_node;

   else  /* if the queue is not empty */

      queue->rear->next=new_node;

   queue->rear=new_node;

}

 

/* removes an element from the front of the queue */

void dequeue(Q_TYPE *queue, ITEM_TYPE *front_item)

{  NODE_PTR temp_ptr;

 

   *front_item=queue->front->item;

   temp_ptr=queue->front;

   queue->front=queue->front->next;

   if (empty_queue(queue)==TRUE)

      queue->rear=NULL;

   free(temp_ptr);

}