J.E.D.I
3 Queues
3.1 Objectives
At the end of the lesson, the student should be able to:
• Define the basic concepts and operations on the ADT queue • Implement the ADT queue using sequential and linked representation
• Perform operations on circular queue • Use topological sorting in producing an order of elements satisfying a given
partial order
3.2 Introduction
A queue is a linearly ordered set of elements that has the discipline of First-In, First-Out. Hence, it is also known as a FIFO list.
There are two basic operations in queues: 1 insertion at the rear, and 2 deletion at the front.
To define the ADT queue in Java, we have the following interface: interface Queue{
Insert an item void enqueueObject item throws QueueException;
Delete an item Object dequeue throws QueueException;
} Just like in stack, we will make use of the following exception:
class QueueException extends RuntimeException{ public QueueExceptionString err{
supererr; }
}
3.3 Representation of Queues
Just like stack, queue may also be implemented using sequential representation or linked allocation.
Data Structures 40
J.E.D.I
3.3.1 Sequential Representation
If the implementation uses sequential representation, a one-dimensional arrayvector is used, hence the size is static. The queue is empty if the front = rear and full if front=0
and rear=n. If the queue has data, front points to the actual front, while rear points to the cell after the actual rear. Deletion from an empty queue causes an underflow while
insertion onto a full queue causes an overflow. The following figure shows an example of the ADT queue:
Figure 1.15 Operations on a Queue Figure 1.16
To initialize, we set front and rear to 0: front = 0;
rear = 0;
To insert an item, say x, we do the following:
Q[rear] = item; rear++;
and to delete an item, we do the following: x = Q[front];
front++; To implement a queue using sequential representation:
class SequentialQueue implements Queue{ Object Q[];
int n = 100 ; size of the queue, default 100
int front = 0; front and rear set to 0 initially
int rear = 0; Create a queue of default size 100
SequentialQueue1{ Q = new Object[n];
} Create a queue of the given size
SequentialQueue1int size{ n = size;
Data Structures 41
J.E.D.I
Q = new Object[n]; }
Inserts an item onto the queue public void enqueueObject item throws QueueException{
if rear == n throw new QueueException Inserting into a full queue.;
Q[rear] = item; rear++;
} Deletes an item from the queue
public Object dequeue throws QueueException{ if front == rear throw new QueueException
Deleting from an empty queue.; Object x = Q[front];
front++; return x;
} }
Whenever deletion is made, there is space vacated at the “front-side” of the queue. Hence, there is a need to move the items to make room at the “rear-side” for future
insertion. The method moveQueue implements this procedure. This could be invoked when
void moveQueue throws QueueException{ if front==0 throw new
QueueExceptionInserting into a full queue; forint i=front; in; i++
Q[i-front] = Q[i]; rear = rear - front;
front = 0; }
There is a need to modify the implementation of enqueue to make use of moveQueue: public void enqueueObject item{
if rear is at the end of the array if rear == n moveQueue;
Q[rear] = item; rear++;
}
3.3.2 Linked Representation
Linked allocation may also be used to represent a queue. It also makes use of nodes with fields INFO and LINK. The following figure shows a queue implemented as a linked list:
Figure 1.17 Linked Representation of a Queue
Data Structures 42
J.E.D.I
The node definition in chapter 1 will also be used here. The queue is empty if front = null. In linked representation, since the queue grows
dynamically, overflow will happen only when the program runs out of memory and dealing with that is beyond the scope of this topic.
The following Java code implements the linked representation of the ADT queue: class LinkedQueue implements Queue{
queueNode front, rear; Create an empty queue
LinkedQueue{ }
Create a queue with node n initially LinkedQueuequeueNode n{
front = n; rear = n;
} Inserts an item onto the queue
public void enqueueObject item{ queueNode n = new queueNodeitem, null;
if front == null { front = n;
rear = n; }
else{ rear.link = n;
rear = n; }
} Deletes an item from the queue
public Object dequeue throws QueueException{ Object x;
if front == null throw new QueueException Deleting from an empty queue.;
x = front.info; front = front.link;
return x; }
}
3.4 Circular Queue
A disadvantage of the previous sequential implementation is the need to move the elements, in the case of rear = n and front 0, to make room for insertion. If queues
are viewed as circular instead, there will be no need to perform such move. In a circular queue, the cells are considered arranged in a circle. The front points to the actual
element at the front of the queue while the rear points to the cell on the right of the actual rear element clockwise. The following figure shows a circular queue:
Data Structures 43
J.E.D.I
Figure 1.18 Circular Queue Figure 1.19
To initialize a circular queue: front = 0;
rear = 0; To insert an item, say x:
Q[rear] = x; rear = rear + 1 mod n;
To delete: x = Q[front];
front = front + 1 mod n;
We use the modulo function instead of performing an if test in incrementing rear and front. As insertions and deletions are done, the queue moves in a clockwise
direction. If front catches up with rear, i.e., if front = rear, then we get an empty queue. If rear catches up with front, a condition also indicated by front
= rear, then all cells are in use and we get a full queue. In order to avoid having the same relation signify two different conditions, we will not allow rear to
catch up with front by considering the queue as full when exactly one free cell remains. Thus a full queue is indicated by:
front == rear + 1 mod n The following methods are implementations of inserting into and deleting from a circular
queue:
Data Structures 44
J.E.D.I
public void enqueueObject item throws QueueException{ if front == rear n + 1 throw new QueueException
Inserting into a full queue.; Q[rear] = item;
rear = rear n + 1; }
public Object dequeue throws QueueException{ Object x;
if front == rear throw new QueueException Deleting from an empty queue.;
x = Q[front]; front = front n + 1;
return x; }
3.5 Application: Topological Sorting