Another commonly used data structure is the queue. A queue is similar to a checkout line in a supermarket—the cashier services the person at the beginning of the line first. Other customers enter the line only at the end and wait for service. Queue nodes are removed only from the head (or front) of the queue and are inserted only at the tail (or end). For this reason, a queue is a first-in, first-out (FIFO) data structure. The insert and remove operations are known as enqueue and dequeue.
Queues have many uses in computer systems. Computers with only a single processor can service only one app at a time. Each app requiring processor time is placed in a queue. The app at the front of the queue is the next to receive service. Each app gradually advances to the front as the apps before it receive service.
Queues are also used to support print spooling. For example, a single printer might be shared by all users of a network. Many users can send print jobs to the printer, even when the printer is already busy. These print jobs are placed in a queue until the printer becomes available. A program called a spooler manages the queue to ensure that as each print job completes, the next one is sent to the printer.
Information packets also wait in queues in computer networks. Each time a packet arrives at a network node, it must be routed to the next node along the path to the packet’s final destination. The routing node routes one packet at a time, so additional packets are enqueued until the router can route them.
A file server in a computer network handles file-access requests from many clients throughout the network. Servers have a limited capacity to service requests from clients. When that capacity is exceeded, client requests wait in queues.
List
The code in Fig. 19.16 creates a queue class by inheriting from a list class. We want the QueueInheritance
class (Fig. 19.16) to have methods Enqueue
, Dequeue
, IsEmpty
and Display
. Essentially, these are the methods InsertAtBack
, RemoveFromFront
, IsEmpty
and Display
of class List
. Of course, the list class contains other methods (such as InsertAtFront
and RemoveFromBack
) that we would rather not make accessible through the public
interface to the queue class. Remember that all methods in the public
interface of the List
class are also public
methods of the derived class QueueInheritance
.
The implementation of each QueueInheritance
method calls the appropriate List
method—method Enqueue
calls InsertAtBack
and method Dequeue
calls RemoveFrom-Front
. Calls to IsEmpty
and Display
invoke the base-class versions that were inherited from class List
into QueueInheritance
’s public
interface. Class QueueInheritance
uses namespace LinkedListLibrary
(Fig. 19.4); thus, the class library for QueueInheritance
must have a reference to the LinkedListLibrary
class library. Just as we demonstrated with stacks, we could use composition to implement a queue class that does not expose the unwanted methods of class List
.
Class QueueTest
’s Main
method (Fig. 19.17) creates a QueueInheritance
object called queue
. Lines 15–18 define four values that will be enqueued and dequeued. The program enqueues (lines 21, 23, 25 and 27) a bool
containing true
, a char
containing '$'
, an int
containing 34567
and a string
containing "hello"
. Class QueueTest
uses namespace LinkedListLibrary
and namespace QueueInheritanceLibrary
; thus, the solution for class QueueTest
must have references to both class libraries.
An infinite while
loop (lines 36–41) dequeues the elements from the queue in FIFO order. When there are no objects left to dequeue, method Dequeue
throws an Empty-ListException
, and the program displays the exception’s stack trace, which shows the program-execution stack at the time the exception occurred. The program uses method Display
(inherited from class List
) to output the contents of the queue after each operation.