Unit 4 - Queues
Unit 4 - Queues
Unit 4: Queues
Introductionto Queues
Array Representation of Queues
Linked Representation of Queues
Types of Queues
Circular Queues
Dequeues
Priority Queues
Multiple Queues
Applications of Queues
Introduction to Queues
Let us explain the concept of queues using the
analogies given below.
People moving on an escalator. The people who
got on the escalator first will be the first one to
step out of it.
People waiting for a bus. The first person standing
in the line will be the first one to get into the bus.
People standing outside the ticketing window of a
cinema hall. The first person in the line will get
the ticket first and thus will be the first one to
move out of it.
Luggage kept on conveyor belts. The bag which
was placed first will be the first to come out at the
other end.
Cars lined at a toll bridge. The first car to reach
the bridge will be the first to leave.
Data Structures and Algoritim, BSCS
AIOU, Furqan Ahmed Ghauri
4
Introduction to Queues
In all these examples, we see that the
element at the first position is served first.
Same is the case with queue data structure.
A queue is a FIFO (First-In, First-Out) data
structure in which the element that is
inserted first is the first one to be taken out.
The elements in a queue are added at one
end called the REAR and removed from the
other end called the FRONT.
Queues can be implemented by using either
arrays or linked lists.
In this section, we will see how queues are
implemented using each of these data
structures.
Data Structures and Algoritim, BSCS
AIOU, Furqan Ahmed Ghauri
5
Types Of Queues
A queue data structure can be classified
into the following types:
1. Circular Queue
2. Deque
3. Priority Queue
4. Multiple Queue
We will discuss each of these queues in
detail in the following sections.
Circular Queues
In linear queues, we have discussed so far
that insertions can be done only at one
end called the REAR and deletions are
always done from the other end called the
FRONT.
Look at the queue shown in Fig. 8.13.
Here, FRONT = 0 and REAR = 9.
Circular Queues
Now, if you want to insert another value, it will not
be possible because the queue is completely full.
There is no empty space where the value can be
inserted.
Consider a scenario in which two successive
deletions are made. The queue will then be given
as shown in Fig. 8.14.
Here, FRONT = 2 and REAR = 9.
Circular Queues
Suppose we want to insert a new element in the queue shown in Fig. 8.14.
Even though there is space available, the overflow condition still exists
because the condition REAR = MAX – 1 still holds true.
This is a major drawback of a linear queue. To resolve this problem, we have
two solutions.
First, shift the elements to the left so that the vacant space can be occupied
and utilized efficiently.
But this can be very time-consuming, especially when the queue is quite
large. The second option is to use a circular queue.
In the circular queue, the first index comes right after the last index.
Conceptually, you can think of a circular queue as shown in Fig. 8.15.
The circular queue will be full only when FRONT = 0 and REAR = Max – 1.
A circular queue is implemented in the same manner as a linear queue is
implemented.
The only difference will be in the code that performs insertion and deletion
operations.
Circular Queues
For insertion, we now have to check for the following three conditions:
If FRONT = 0 and REAR = MAX – 1, then the circular queue is full. Look
at the queue given in Fig. 8.16 which illustrates this point.
If REAR != MAX – 1, then REAR will be incremented and the value will
be inserted as illustrated in Fig. 8.17.
If FRONT != 0 and REAR = MAX – 1, then it means that the queue is not
full. So, set REAR = 0 and insert the new element there, as shown in
Fig. 8.18.
Circular Queues
Let us look at Fig. 8.19 which shows the algorithm to insert an
element in a circular queue.
In Step 1, we check for the overflow condition. In Step 2, we
make two checks.
First to see if the queue is empty, and second to see if the
REAR end has already reached the maximum capacity while
there are certain free locations before the FRONT end.
In Step 3, the value is stored in the queue at the location
pointed by REAR.
Circular Queues
Circular Queues
Dequeues
A deque (pronounced as ‘deck’ or ‘dequeue’) is a list in which the
elements can be inserted or deleted at either end.
It is also known as a head-tail linked list because elements can be
added to or removed from either the front (head) or the back (tail)
end.
However, no element can be added and deleted from the middle. In
the computer’s memory, a deque is implemented using either a
circular array or a circular doubly linked list.
In a deque, two pointers are maintained, LEFT and RIGHT, which
point to either end of the deque.
The elements in a deque extend from the LEFT end to the RIGHT end
and since it is circular, Dequeue[N–1] is followed by Dequeue[0].
Consider the deques shown in Fig. 8.24.
Dequeues
There are two variants of a double-ended
queue. They include:
Input restricted deque: In this dequeue,
insertions can be done only at one of the
ends, while deletions can be done from
both ends.
Output restricted deque: In this dequeue,
deletions can be done only at one of the
ends, while insertions can be done on
both ends.
Priority Queues
A priority queue is a data structure in
which each element is assigned a priority.
The priority of the element will be used to
determine the order in which the
elements will be processed.
The general rules of processing the
elements of a priority queue are:
An element with higher priority is
processed before an element with a lower
priority.
Two elements with the same priority are
processed on a first-come-first-served
(FCFS) basis.
Data Structures and Algoritim, BSCS
AIOU, Furqan Ahmed Ghauri
36
Priority Queues
A priority queue can be thought of as a modified queue in which
when an element has to be removed from the queue, the one
with the highest-priority is retrieved first. The priority of the
element can be set based on various factors.
Priority queues are widely used in operating systems to execute
the highest priority process first.
The priority of the process may be set based on the CPU time it
requires to get executed completely.
For example, if there are three processes, where the first
process needs 5 ns to complete, the second process needs 4 ns,
and the third process needs 7 ns, then the second process will
have the highest priority and will thus be the first to be
executed.
However, CPU time is not the only factor that determines the
priority, rather it is just one among several factors.
Another factor is the importance of one process over another. In
case we have to run two processes at the same time, where one
process is concerned with online order booking and the second
with printing of stock details, then obviously the online booking
is more important and must be executed first.
Priority Queues
Implementation of a Priority Queue
There are two ways to implement a priority queue.
We can either use a sorted list to store the elements so
that when an element has to be taken out, the queue will
not have to be searched for the element with the highest
priority or we can use an unsorted list so that insertions
are always done at the end of the list.
Every time when an element has to be removed from the
list, the element with the highest priority will be
searched and removed.
While a sorted list takes O(n) time to insert an element
in the list, it takes only O(1) time to delete an element.
On the contrary, an unsorted list will take O(1) time to
insert an element and O(n) time to delete an element
from the list.
Practically, both these techniques are inefficient and
usually a blend of these two approaches is adopted that
takes roughly O(log n) time or less.
Data Structures and Algoritim, BSCS
AIOU, Furqan Ahmed Ghauri
38
Priority Queues
Linked Representation of a Priority Queue
In the computer memory, a priority queue can be
represented using arrays or linked lists.
When a priority queue is implemented using a linked
list, then every node of the list will have three parts:
(a) the information or data part, (b) the priority number
of the element, and (c) the address of the next
element.
If we are using a sorted linked list, then the element
with the higher priority will precede the element with
the lower priority.
Consider the priority queue shown in Fig. 8.25.
Priority Queues
Lower priority number means higher priority.
For example, if there are two elements A and B,
where A has a priority number 1 and B has a
priority number 5, then A will be processed before
B as it has higher priority than B.
The priority queue in Fig. 8.25 is a sorted priority
queue having six elements.
From the queue, we cannot make out whether A
was inserted before E or whether E joined the
queue before A because the list is not sorted based
on FCFS.
Here, the element with a higher priority comes
before the element with a lower priority.
However, we can definitely say that C was inserted
in the queue before D because when two elements
have the same priority the elements are arranged
and processed on FCFS principle.
Data Structures and Algoritim, BSCS
AIOU, Furqan Ahmed Ghauri
40
Priority Queues
Insertion When a new element has to be inserted in a
priority queue, we have to traverse the entire list until we
find a node that has a priority lower than that of the new
element.
The new node is inserted before the node with the lower
priority.
However, if there exists an element that has the same
priority as the new element, the new element is inserted
after that element.
For example, consider the priority queue shown in Fig. 8.26.
Priority Queues
Ifwe have to insert a new element with
data = F and priority number = 4, then
the element will be inserted before D that
has priority number 5, which is lower
priority than that of the new element.
So, the priority queue now becomes as
shown in Fig. 8.27.
Priority Queues
However, if we have a new element with data =
F and priority number = 2, then the element will
be inserted after B, as both these elements
have the same priority but the insertions are
done on FCFS basis as shown in Fig. 8.28.
Priority Queues
When arrays are used to implement a priority queue, then a
separate queue for each priority number is maintained.
Each of these queues will be implemented using circular
arrays or circular queues.
Every individual queue will have its own FRONT and REAR
pointers.
We use a two-dimensional array for this purpose where each
queue will be allocated the same amount of space.
Look at the two-dimensional representation of a priority
queue given below.
Given the FRONT and REAR values of each queue, the two-
dimensional matrix can be formed as shown in Fig. 8.29.
Priority Queues
FRONT[K] and REAR[K] contain the front and rear values of
row K, where K is the priority number.
Note that here we are assuming that the row and column
indices start from 1, not 0.
Obviously, while programming, we will not take such
assumptions.
Insertion
To insert a new element with priority K in the priority queue,
add the element at the rear end of row K, where K is the row
number as well as the priority number of that element.
For example, if we have to insert an element R with priority
number 3, then the priority queue will be given as shown in
Fig. 8.30.
Priority Queues
Deletion
To delete an element, we find the first
nonempty queue and then process the
front element of the first non-empty
queue.
In our priority queue, the first non-empty
queue is the one with priority number 1
and the front element is A, so A will be
deleted and processed first.
In technical terms, find the element with
the smallest K, such that FRONT[K] !=
NULL.
Priority Queues
Priority Queues
Priority Queues
Multiple Queues
When we implement a queue using an array, the
size of the array must be known in advance.
If the queue is allocated less space, then frequent
overflow conditions will be encountered.
To deal with this problem, the code will have to be
modified to reallocate more space for the array.
In case we allocate a large amount of space for
the queue, it will result in sheer wastage of the
memory.
Thus, there lies a tradeoff between the frequency
of overflows and the space allocated.
So a better solution to deal with this problem is to
have multiple queues or to have more than one
queue in the same array of sufficient size.
Figure 8.31 illustrates this concept.
Multiple Queues
In the figure, an array QUEUE[n] is used to
represent two queues, QUEUE A and QUEUE B.
The value of n is such that the combined size of
both the queues will never exceed n.
While operating on these queues, it is
important to note one thing—QUEUE A will grow
from left to right, whereas QUEUE B will grow
from right to left at the same time.
Extending the concept to multiple queues, a
queue can also be used to represent n number
of queues in the same array.
That is, if we have a QUEUE[n], then each
QUEUE I will be allocated an equal amount of
space bounded by indices b[i] and e[i].
This is shown in Fig. 8.32.
Data Structures and Algoritim, BSCS
AIOU, Furqan Ahmed Ghauri
51
Multiple Queues
Application of Queues:
Simulation
Simulation
Technique in which one system models
the behavior of another system
Computer simulation
Represents objects being studied as data
Actions implemented with algorithms
Programming language implements
algorithms with functions
Functions implement object actions
Application of Queues:
Simulation (cont’d.)
Computer simulation (cont’d.)
C++ combines data, data operations into a single
unit using classes
Objects represented as classes
Class member variables describe object properties
Function members describe actions on data
Change in simulation results occurs if change in
data value or modification of function definitions
occurs
Main goal
Generate results showing the performance of an
existing system
Predict performance of a proposed system
Data Structures Using C++ 2E
54
Application of Queues:
Simulation (cont’d.)
Queuing systems
Computer simulations
Queues represent the basic data structure
Queues of objects
Waiting to be served by various servers
Consist of servers and queues of objects
waiting to be served