Queues
QUEUES
The queue is an ordered group of elements in which new elements are added at one end (the rear) and elements are removed at the other end (the front).
The queue is known as a FIFO data structure because the first element added is the first element removed
-- first in, first out.
A familiar example of a queue is a checkout line in a grocery store. The first person in line is the first to be served. People are served according to the order of their arrival ? first come first served.
A practical example of a queue in computing is the printer queue, which is a list of files to be printed. The first file to be queued is the first to be printed.
Regardless of the implementation of the queue only the elements at the front and rear of the queue are accessible. The middle elements are logically inaccessible.
QUEUE OPERATIONS
There is a group of basic queue operations with which the programmer should be familiar.
1. Determining if the queue is empty before attempting to remove an element.
emptyQueue returns TRUE if the queue is empty, FALSE otherwise.
2. Clearing the queue or initializing it to the empty state.
3. Adding an element to the queue. This will be called en-queue (enqueue). The statement
enqueue(X) means add item X to the rear of the queue.
4. Removing an element from the queue. This will be called de-queue (dequeue). The statement
dequeue(X) means remove the front element from the queue and return it in X. (Note that unlike POP and PUSH for stacks there are no standard names for the addition and removal of elements from queues. They are sometimes called ADD and REMOVE or INSERT and DELETE.)
IMPLEMENTATION
Queues can be implemented in a variety of ways. Stacks and queues can vary greatly in size during run time, and thus are best implemented as dynamic linked lists. The implementation should not affect the code in the higher levels of the program. Only low-level routines like enqueue and dequeue, and the declarations for the data structure will need to be modified.
Declarations
A queue can be implemented in a linked list by keeping two external pointers to the list -- one to the node on each end.

The class specification appears below.
'--------------------------------------------------------------------- ' linkNode class '--------------------------------------------------------------------- ' instance variables Private info As Variant Private nextNode As linkNode ' class methods '--------------------------------------------------------------------- ' Constructor '--------------------------------------------------------------------- Private Sub Class_Initialize( ) Set nextNode = Nothing End Sub '--------------------------------------------------------------------- ' Set node value '--------------------------------------------------------------------- Public Sub setInfo(ByVal newValue As Variant) info = newValue End Sub '--------------------------------------------------------------------- ' Return node value '--------------------------------------------------------------------- Public Function getInfo( ) As Variant getInfo = info End Function '--------------------------------------------------------------------- ' Reset nextNode reference '--------------------------------------------------------------------- Public Sub setNextNode(ByRef followingNode As linkNode) Set nextNode = followingNode End Sub '--------------------------------------------------------------------- ' Return nextNode reference '--------------------------------------------------------------------- Public Function getNextNode( ) As linkNode Set getNextNode = nextNode End Function |
'--------------------------------------------------------------------- ' clsQueue class '--------------------------------------------------------------------- Private qFront As linkNode Private qRear As linkNode '--------------------------------------------------------------------- ' Inserts an element at the rear of the queue. '--------------------------------------------------------------------- Public Sub enqueue(ByVal newValue As Variant) Dim Ptr As New linkNode Call Ptr.setInfo(newValue) Call Ptr.setNextNode(Nothing) If qRear Is Nothing Then Set qRear = Ptr Set qFront = Ptr Else Call qRear.setNextNode(Ptr) Set qRear = Ptr End If End Sub '--------------------------------------------------------------------- ' Returns true if queue is empty, false otherwise. '--------------------------------------------------------------------- Public Function emptyQueue( ) As Boolean emptyQueue = (qFront Is Nothing) And (qRear Is Nothing) End Function '--------------------------------------------------------------------- ' Initializes the queue to the empty state. '--------------------------------------------------------------------- Public Sub clearQueue( ) Set qFront = Nothing Set qRear = Nothing End Sub '--------------------------------------------------------------------- ' Removes an element from the front of the queue. '--------------------------------------------------------------------- Public Function dequeue( ) As Variant Dim deqNode As linkNode If emptyQueue( ) Then MsgBox "Queue empty -- no item to dequeue.", vbOKCancel + _ vbExclamation + vbApplicationModal, "Dequeue Alert" Else Set deqNode = qFront Set qFront = qFront.getNextNode( ) dequeue = deqNode .getInfo( ) Call deqNode.setNextNode( Nothing) Set deqNode = Nothing If qFront Is Nothing Then Set qRear = Nothing End If End Function
'--------------------------------------------------------------------- |
Stack Operations
CLEAR QUEUE:
Clearing the queue is accomplished by setting qFront and qRear, the external pointers to the
queue, to Nothing.
'--------------------------------------------------------------------- ' Initializes the queue to the empty state. '--------------------------------------------------------------------- Public Sub clearQueue( ) Set qFront = Nothing Set qRear = Nothing End Sub |
EMPTY QUEUE:
Testing for an empty queue can be done by checking to see if the external
pointers, qFront and qRear, equal Nothing.
'--------------------------------------------------------------------- ' Returns true if queue is empty, false otherwise. '--------------------------------------------------------------------- Public Function emptyQueue( ) As Boolean emptyQueue = (qFront Is Nothing) And (qRear Is Nothing) End Function |
ENQUEUE
The insertion algorithm for inserting an element at
qRear must take care of two cases: when the queue is empty and when it has one or more elements.
'--------------------------------------------------------------------- ' Inserts an element at the rear of the queue. '--------------------------------------------------------------------- Public Sub enqueue (ByVal newValue As Variant) Dim newNode As New linkNode Call newNode.setInfo(newValue) Call newNode.setNextNode(Nothing) If qRear Is Nothing Then Set qRear = newNode Set qFront = newNode Else Call qRear.setNextNode(newNode) Set qRear = newNode End If End Sub |
Dim newNode As New linkNode
Call newNode.setInfo(newValue)

Call qRear.setNextNode( newNode)

Set qRear = newNode

DEQUEUE
Removing an element
from the front of a queue is similar to popping an element from a stack. The only addition is a check to see if the queue is empty after removing the element. If it is, qRear is set to Nothing.
'--------------------------------------------------------------------- ' Removes an element from the front of the queue. '--------------------------------------------------------------------- Public Function dequeue( ) As Variant Dim deqNode As linkNode If emptyQueue( ) Then MsgBox "Queue empty -- no item to dequeue.", vbOKCancel + _ vbExclamation + vbApplicationModal, "Dequeue Alert" Else Set deqNode = qFront Set qFront = qFront.getNextNode( ) dequeue = deqNode .getInfo( ) Call deqNode.setNextNode(Nothing) Set deqNode = Nothing If qFront Is Nothing Then Set qRear = Nothing End If End Function |
Set deqNode = qFront

Set qFront = qFront.getNextNode( )

Call deqNode.setNextNode( Nothing)

Set deqNode = Nothing

<garbage collection>
Implementation Note:
Queues can be implemented using a circular linked list. If the external pointer to the list, or queue, points to the last node, both ends of the queue can be accessed. This makes it possible to implement queue operations using one pointer to the queue, rather than separate pointers to the front and rear.
In order to en-queue, the rear node can be accessed through the external pointer
, and in order to de-queue, the front node can be accessed through the nextNode
field of queue. An empty queue would be represented by
the condition
queue Is Nothing.
Applications
Queues are used extensively in operating system software. In
multi-user systems the operating system has a job queue of programs waiting to be executed. As each program reaches the front of the queue, its execution is initiated. In addition, many users share many I/O devices and each device has a queue of requests
for use.
Test Module
'--------------------------------------------------------------------- ' Test module '--------------------------------------------------------------------- Private Sub Form_Load( ) Dim queue As New clsQueue Dim p As Variant Call queue.enqueue("A") Call queue.printQueue( ) Call queue.enqueue("B") Call queue.printQueue( ) Call queue.enqueue("C") Call queue.printQueue( ) p = queue.dequeue( ) Call queue.printQueue( ) p = queue.dequeue( ) Call queue.printQueue( ) p = queue.dequeue( ) Call queue.printQueue( ) p = queue.dequeue( ) Call queue.printQueue( ) Call queue.enqueue("A") Call queue.printQueue( ) Call queue.clearQueue( ) Call queue.printQueue( ) End Sub |