Notes on Queues

Download Report

Transcript Notes on Queues

CSCI 3333 Data Structures
Queues
Acknowledgement






Dr. Bun Yue
Mr. Charles Moen
Dr. Wei Ding
Ms. Krishani Abeysekera
Dr. Michael Goodrich
Dr. Richard F. Gilberg
Queues

First In First Out (FIFO) data
structure.
Queue Concept
Queues




The Queue ADT stores arbitrary objects
Insertions and deletions follow the first-in
first-out scheme
Insertions are at the rear of the queue
and removals are at the front of the
queue
Main queue operations:


enqueue(object): inserts an element at the
end of the queue
object dequeue(): removes and returns the
element at the front of the queue
Queue Operations

Some auxiliary queue operations:




object front(): returns the element at the front
without removing it
integer size(): returns the number of elements
stored
boolean isEmpty(): indicates whether no
elements are stored
Exceptions

Attempting the execution of dequeue or front
on an empty queue throws an
EmptyQueueException
Queue Example
Operation
enqueue(5)
enqueue(3)
dequeue()
enqueue(7)
dequeue()
front()
dequeue()
dequeue()
isEmpty()
enqueue(9)
enqueue(7)
size()
enqueue(3)
enqueue(5)
dequeue()
Output Q
–
(5)
–
(5, 3)
5
(3)
–
(3, 7)
3
(7)
7
(7)
7
()
“error” ()
true
()
–
(9)
–
(9, 7)
2
(9, 7)
–
(9, 7, 3)
–
(9, 7, 3, 5)
9
(7, 3, 5)
Some Implementation Criteria

As queues are general data
structures for widespread use, there
are variations to fit different
applications. Some considerations:





Implementation: array vs. linked list.
Thread safe or not.
Blocking or not.
Synchronous or not.
Allow null elements or not.
Applications of Queues

Some direct applications







Waiting lists, bureaucracy
Access to shared resources (e.g., printer)
Simulation
Breadth-first traversals
Multiprogramming
Messaging
Indirect applications


Auxiliary data structure for algorithms
Component of other data structures
Array-based Queue


Use an array of size N in a circular fashion
Two variables keep track of the front and rear
f index of the front element
r index immediately past the rear element

Array location r is kept empty
normal configuration
Q
0 1 2
f
r
wrapped-around configuration
Q
0 1 2
r
f
Queue Operations

We use the
modulo operator
(remainder of
division)
Algorithm size()
return (N - f + r) mod N
Algorithm isEmpty()
return (f = r)
Q
0 1 2
f
0 1 2
r
r
Q
f
Queue Operations (cont.)


Operation enqueue
throws an exception if
the array is full
This exception is
implementationdependent
Algorithm enqueue(o)
if size() = N - 1 then
throw FullQueueException
else
Q[r]  o
r  (r + 1) mod N
Q
0 1 2
f
0 1 2
r
r
Q
f
Queue Operations (cont.)


Operation dequeue
throws an exception
if the queue is empty
This exception is
specified in the
queue ADT
Algorithm dequeue()
if isEmpty() then
throw EmptyQueueException
else
o  Q[f]
f  (f + 1) mod N
return o
Q
0 1 2
f
0 1 2
r
r
Q
f
Linked List Implementation

We have already implemented
methods necessary for the queue
ADT (under different method
names) using a singly linked list.
Application: Round Robin Schedulers

We can implement a round robin scheduler using a
queue, Q, by repeatedly performing the following
steps:
1.
2.
3.
e = Q.dequeue()
Service element e
Q.enqueue(e)
The Queue
1. Deque the
next element
2 . Service the
next element
Shared
Service
3. Enqueue the
serviced element
Palindrome in C++: Spot the error
#include “Stack.h”;
#include “Queue.h”;
#include <iostream.h>
using namespace std;
int main() {
// Incorrect solution. Can you see it?
Stack
S;
Queue
Q;
char ch;
cout << “Enter string to be tested as palindrome: “;
while (cin >> ch) {
S.push(ch);
Q.enqueue(ch);
}
bool pal = true;
while (!Q.isEmpty())
pal = Q.dequeue() = = S.pop();
if (pal)
cout << “Palindrome!!” << endl;
return EXIT_SUCCESS; }
Example: Queue in Ruby



Ruby is a newer object oriented
scripting language using some
software engineering principles.
We use a queue example in Ruby to
illustrative the use of queues for
concurrent processes.
There is no need to understand all
details of the example.
Queue.rb
require 'thread'
queue = Queue.new
producer = Thread.new do
# concurrent thread 1
5.times do |i|
sleep rand(i) # simulate expense
queue << i
puts "#{i} produced"
end
end
consumer = Thread.new do
# concurrent thread 2
5.times do |i|
value = queue.pop
sleep rand(i/2) # simulate expense
puts "consumed #{value}"
end
end
consumer.join
Executing Queue.rb
0 produced
1 produced
consumed 0
2 produced
consumed 1
consumed 2
3 produced
consumed 3
4 produced
consumed 4
Questions and Comments?