1. Data Structures & Algorithms
Lecture 2d: Queue Data StructuresLecture 2d: Queue Data Structures
Joan Wakasa MurumbaJoan Wakasa Murumba
2. Queue ADT
Like a stack, aLike a stack, a queuequeue is also a list.is also a list.
However, with a queue, insertion is done atHowever, with a queue, insertion is done at
one end, while deletion is performed at theone end, while deletion is performed at the
other end.other end.
Accessing the elements of queues follows aAccessing the elements of queues follows a
First In, First Out (FIFO) order.First In, First Out (FIFO) order.
Like customers standing in a check-outLike customers standing in a check-out
line in a store, the first customer in is theline in a store, the first customer in is the
first customer served.first customer served.
3. The Queue ADT
Another form of restricted listAnother form of restricted list
Insertion is done at one end, whereasInsertion is done at one end, whereas
deletion is performed at the other enddeletion is performed at the other end
Basic operations:Basic operations:
EnqueueEnqueue
DequeueDequeue
First-in First-out (FIFO) listFirst-in First-out (FIFO) list
5. Enqueue and Dequeue
Primary queue operations: Enqueue andPrimary queue operations: Enqueue and
DequeueDequeue
Like check-out lines in a store, a queue has aLike check-out lines in a store, a queue has a
front and a rear.front and a rear.
EnqueueEnqueue
Insert an element at the rear of the queueInsert an element at the rear of the queue
DequeueDequeue
Remove/delete an element from the front ofRemove/delete an element from the front of
the queuethe queue
7. The Queue Operations
A queue is like a line of peopleA queue is like a line of people
waiting for a bank teller. The queuewaiting for a bank teller. The queue
has ahas a frontfront and aand a rearrear..
$ $
Front
Rear
8. The Queue Operations
New people must enter the queue at theNew people must enter the queue at the
rear.rear.
The C++ queue class calls this aThe C++ queue class calls this a pushpush,,
although it is usually called analthough it is usually called an enqueueenqueue
operation.operation.
$ $
Front
Rear
9. The Queue Operations
When an item is taken from the queue, itWhen an item is taken from the queue, it
always comes from the front. The C++always comes from the front. The C++
queue calls this aqueue calls this a poppop, although it is usually, although it is usually
called acalled a dequeuedequeue operation.operation.
$ $
Front
Rear
10. Array Implementation of Queue
When enqueuing, theWhen enqueuing, the front indexfront index is always fixedis always fixed
and theand the rear indexrear index moves forward in the array.moves forward in the array.
There are several different algorithms toThere are several different algorithms to
implement Enqueue and Dequeueimplement Enqueue and Dequeue
front
rear
Enqueue(3)
3
front
rear
Enqueue(6)
3 6
front
rear
Enqueue(9)
3 6 9
11. Queue Implementation of Array
When enqueuing, theWhen enqueuing, the front indexfront index is always fixedis always fixed
and theand the rear indexrear index moves forward in the array.moves forward in the array.
When dequeuing, the element at the front of theWhen dequeuing, the element at the front of the
queue is removed. Move all the elements after itqueue is removed. Move all the elements after it
by one position. (Inefficient!!!)by one position. (Inefficient!!!)
Dequeue()
front
rear
6 9
Dequeue() Dequeue()
front
rear
9
rear = -1
front
12. Queue Implementation of Array
Better wayBetter way
When an item is enqueued, make theWhen an item is enqueued, make the rearrear
indexindex move forward.move forward.
When an item is dequeued, theWhen an item is dequeued, the front indexfront index
moves by one element towards the back ofmoves by one element towards the back of
the queue (thus removing the front item, sothe queue (thus removing the front item, so
no copying to neighboring elements isno copying to neighboring elements is
needed).needed).
13. Array Implementation....
A queue can be implemented with an array.A queue can be implemented with an array.
For example, this queue contains the integersFor example, this queue contains the integers
4 (at the front), 8 and 6 (at the rear).4 (at the front), 8 and 6 (at the rear).
[[ 0 ]0 ] [1][1] [ 2 ][ 2 ] [ 3 ][ 3 ] [ 4 ][ 4 ] [ 5 ][ 5 ] . .. ...
An array of integers toAn array of integers to
implement a queue ofimplement a queue of
4 8 6
14. Array Implementation....
The easiest implementation alsoThe easiest implementation also
keeps track of the number of itemskeeps track of the number of items
in the queue and the index of thein the queue and the index of the
first element (at the front of thefirst element (at the front of the
queue), the last element (at thequeue), the last element (at the
rear).rear).
[ 0 ][ 0 ] [1][1] [ 2 ][ 2 ] [ 3 ][ 3 ] [ 4 ][ 4 ] [ 5 ][ 5 ] . . .. . .
4 8 6
sizesize3
firstfirst0
lastlast2
15. A Dequeue Operation....
When an element leaves theWhen an element leaves the
queue, size is decremented,queue, size is decremented,
and first changes, too.and first changes, too.
[ 0 ][ 0 ] [1][1] [ 2 ][ 2 ] [ 3 ][ 3 ] [ 4 ][ 4 ] [ 5 ][ 5 ] . . .. . .
4 8 6
sizesize2
firstfirst1
lastlast2
16. An Enqueue Operation....
When an element enters theWhen an element enters the
queue, size is incremented, andqueue, size is incremented, and
last changes, too.last changes, too.
[ 0 ][ 0 ] [1][1] [ 2 ][ 2 ] [ 3 ][ 3 ] [ 4 ][ 4 ] [ 5 ][ 5 ] . . .. . .
28 6
sizesize3
firstfirst1
lastlast3
17. At the End of the Array...
There is special behaviour at theThere is special behaviour at the
end of the array.end of the array.
For example, suppose we want toFor example, suppose we want to
add a new element to this queue,add a new element to this queue,
where the last index is [5]:where the last index is [5]:
[ 0 ][ 0 ] [1][1] [ 2 ][ 2 ] [ 3 ][ 3 ] [ 4 ][ 4 ] [ 5 ][ 5 ]
2 16
sizesize3
firstfirst3
lastlast5
18. At the End of the Array...
The new element goes at theThe new element goes at the
front of the array (if that spotfront of the array (if that spot
isn’t already used):isn’t already used):
[ 0 ][ 0 ] [1][1] [ 2 ][ 2 ] [ 3 ][ 3 ] [ 4 ][ 4 ] [ 5 ][ 5 ]
2 16
sizesize4
firstfirst3
lastlast0
4
19. 19
..Array implementation of queues
A queue is a first in, first out (FIFO) data structureA queue is a first in, first out (FIFO) data structure
This is accomplished by inserting at one end (theThis is accomplished by inserting at one end (the
rear) and deleting from the other (the front)rear) and deleting from the other (the front)
To insert:To insert: put new element in location 4, andput new element in location 4, and
set rear to 4set rear to 4
To delete:To delete: take element from location 0, and settake element from location 0, and set
front to 1front to 1
17 23 97 44
0 1 2 3 4 5 6 7
myQueue:
rear = 3front = 0
20. 20
…Array implementation of queues
Notice how the array contents “crawl” to theNotice how the array contents “crawl” to the
right as elements are inserted and deletedright as elements are inserted and deleted
This will be a problem after a while!This will be a problem after a while!
17 23 97 44 333After insertion:
23 97 44 333After deletion:
rear = 4front = 1
17 23 97 44Initial queue:
rear = 3front = 0
21. Circular Arrays
We can treat the array holding the queueWe can treat the array holding the queue
elements as circular (joined at the ends)elements as circular (joined at the ends)
44 55 11 22 33
0 1 2 3 4 5 6 7
myQueue:
rear = 1 front = 5
Elements were added to this queue in the order 11,Elements were added to this queue in the order 11,
22, 33, 44, 55, and will be removed in the same order22, 33, 44, 55, and will be removed in the same order
Use: front = (front + 1) % myQueue.length;Use: front = (front + 1) % myQueue.length;
and: rear = (rear + 1) % myQueue.length;and: rear = (rear + 1) % myQueue.length;
22. …Full and empty queues
If the queue were to become completely full, itIf the queue were to become completely full, it
would look like this:would look like this:
If we were then to remove all eight elements,If we were then to remove all eight elements,
making the queue completely empty, it would lookmaking the queue completely empty, it would look
like this:like this:
44 55 66 77 88 11 22 33
0 1 2 3 4 5 6 7
myQueue:
rear = 4 front = 5
0 1 2 3 4 5 6 7
myQueue:
rear = 4 front = 5
This is a problem!
23. Full and empty queues: solutions
Solution #1:Solution #1: Keep an additional variableKeep an additional variable
Solution #2:Solution #2: (Slightly more efficient) Keep a gap(Slightly more efficient) Keep a gap
betweenbetween elements: consider the queue full when itelements: consider the queue full when it
has n-1 elementshas n-1 elements
44 55 66 77 88 11 22 33
0 1 2 3 4 5 6 7
myQueue:
rear = 4 front = 5count = 8
44 55 66 77 11 22 33
0 1 2 3 4 5 6 7
myQueue:
rear = 3 front = 5
24. Advantages of Array
Implementation of a Queue
Easy to implementEasy to implement
But it has a limited capacity with a fixed arrayBut it has a limited capacity with a fixed array
Or you must use a dynamic array for anOr you must use a dynamic array for an
unbounded capacityunbounded capacity
25. Queue Class
IsFull: return true if queue is full, returnIsFull: return true if queue is full, return
false otherwisefalse otherwise
Enqueue: add an element to the rear ofEnqueue: add an element to the rear of
queuequeue
Dequeue: delete the element at the frontDequeue: delete the element at the front
of queueof queue
DisplayQueue: print all the dataDisplayQueue: print all the data
26. Linked List Implementation
10
15
7
null
13
A queue can also beA queue can also be
implemented with a linked listimplemented with a linked list
with both a head and a tailwith both a head and a tail
pointer.pointer.
head_ptr
28. Linked List Implementation
10
15
7
null
head_ptr
13
The head_ptr points to the frontThe head_ptr points to the front
of the list.of the list.
Because it is harder to removeBecause it is harder to remove
items from the tail of the list.items from the tail of the list.
tail_ptr
Front
Rear
29. 29
Enqueueing a node
17
Node to be
enqueued
To Enqueue (add) a node:
Find the current last node
Change it to point to the new last
node
Change the last pointer in the list
header
2344
last
first
97
30. 30
Enqueueing a node
17
Node to be
enqueued
To enqueue (add) a node:
Find the current last node
Change it to point to the new last node
Change the last pointer in the list
header
2344
last
first
97
31. 31
Dequeueing a node
To dequeue (remove) a node:To dequeue (remove) a node:
Copy the pointer from the first node intoCopy the pointer from the first node into
the headerthe header
44 97 23 17
last
first
32. Queue Class
Attributes of QueueAttributes of Queue
front/rear: front/rear indexfront/rear: front/rear index
counter: number of elements in the queuecounter: number of elements in the queue
maxSize: capacity of the queuemaxSize: capacity of the queue
values: point to an array which storesvalues: point to an array which stores
elements of the queueelements of the queue
Operations of QueueOperations of Queue
IsEmpty: return true if queue is empty,IsEmpty: return true if queue is empty,
return false otherwisereturn false otherwise
34. 34
Queue implementation details
With an array implementation:With an array implementation:
You can have both overflow and underflowYou can have both overflow and underflow
You should set deleted elements to nullYou should set deleted elements to null
With a linked-list implementation:With a linked-list implementation:
You can have underflowYou can have underflow
Overflow is a global out-of-memory conditionOverflow is a global out-of-memory condition
There is no reason to set deleted elements to nullThere is no reason to set deleted elements to null
35. 35
Applications of Queues
Direct applicationsDirect applications
Waiting lists, bureaucracyWaiting lists, bureaucracy
Access to shared resources (e.g.,Access to shared resources (e.g.,
printer)printer)
MultiprogrammingMultiprogramming
Indirect applicationsIndirect applications
Auxiliary data structure for algorithmsAuxiliary data structure for algorithms
Component of other data structuresComponent of other data structures
36. 36
Application: Round Robin
Schedulers
We can implement a round robin scheduler using aWe can implement a round robin scheduler using a
queue,queue, QQ, by repeatedly performing the following, by repeatedly performing the following
steps:steps:
1.1. e = Q.e = Q.dequeue()dequeue()
2.2. Service elementService element ee
3.3. Q.Q.enqueue(enqueue(ee))
The Queue
Shared
Service
1
.Dequeue the
next element
3.
Enqueue the
serviced element
2.
Service the
next element
37. 37
Priority Queue Implementation
Sequence-based Priority Queue
Implementation with anImplementation with an
unsorted listunsorted list
Performance:Performance:
insert takesinsert takes OO(1) time(1) time
since we can insert thesince we can insert the
item at the beginning oritem at the beginning or
end of the sequenceend of the sequence
removeMin and min takeremoveMin and min take
OO((nn) time since we have) time since we have
to traverse the entireto traverse the entire
sequence to find thesequence to find the
smallestsmallest keykey
Implementation with aImplementation with a
sorted listsorted list
Performance:Performance:
insert takesinsert takes OO((nn) time) time
since we have to find thesince we have to find the
place where to insert theplace where to insert the
itemitem
removeMin and min takeremoveMin and min take
OO(1) time, since the(1) time, since the
smallest key is at thesmallest key is at the
beginningbeginning
4 5 2 3 1 1 2 3 4 5
When an item is removed from a queue, the removal occurs at the front.
Just like our stack implementation in the previous lecture, one way to implement a queue is to store the elements in an array.
The easiest implementation also keeps track of three numbers. The size could be as small as zero or as large as the number of items in the array. The index of the front element is stored in the first member variable. The front item in the queue is at that index of the array. The next item is after the first one and so on until the rear of the queue that occurs at the index stored in a member variable called last.
This shows how the member variables change when an item leaves the queue.
And this shows how the member variables change when a new item enters the queue. For a fixed size array, a new item may enter only if the current size of the queue is less than the size of the array. For a dynamic array, we could increase the size of the array when the queue grows beyond the current array size.
An array implementation of a queue must have special behavior when the rear of the queue reaches the end of the array. In this example, suppose we want to add the number 4 to the queue. We can do so…
…by putting it at location 0 (if that location is not already used).
A linked list can also be used to implement a queue, but we must maintain both a head and a tail pointer because we need access to both the front and the rear of the queue.
Does it matter which end of a singly-linked list we use for the front of the queue?
Of course, we could put the front of the queue at the end of the linked list, but it would be hard to remove an item. Do you see why?