Sei sulla pagina 1di 5

CSE211 Lecture Notes – 2004/2005-II

CSE 211: Data Structures


Lecture Notes VI
by
Ender Ozcan, Sebnem Baydere

QUEUES
Queues are simple but quite useful data structures. In several applications it is important to be able to
remove the most recently inserted item (stacks) but in some applications this is the wrong way to do.
Consider a multi user multiprocessing system, when jobs are submitted to the printer it is expected that
the least recently submitted job to be printed first. In other words, first submitted to be served first and
last submitted to be served last; simple queue logic. This is also required because we don’t want the
job wait to be served forever. Examples for queues:
n Bank service desk
n Supermarket checkout counters
n Waiting for a bus
n Waiting in front of ticket offices
n Gas stations
n Registration
n These can be implemented using a QUEUE structure.
Items are returned form a queue in first-in, first-out (FIFO) order. Queues have two ends: the front and
the rear. Deletions are made from the front and additions are made to the rear of the queue. Some
basic operations that can be performed on queues are: add, delete, front operations. Add operation
inserts an item to the rear of the queue. We can combine delete and front operations; removes an item
from the front of the queue and returns it in the element called head. We also need to create and
initialize the queue structure.

E D C B A

Rear (Tail) Front (Head)


QUEUE

1. Basic Queue Operations


An item joins the queue only at the tail and leaves the queue only at the head. Only the head item can
be examined. Thus the operations on queues are the initializers (reset a queue), enqueue (put an item
on the queue), dequeue (delete an item from the queue), isQueueEmpty (testing whether a queue is
empty), first (examines the first item without removing it).
CSE211 Lecture Notes – 2004/2005-II

1.1. Implementation of Queues


One way of implementing queues is using arrays, with a cursor indicating the tail of the queue. The
algorithms for queue operations depend on the initialization. If initially, the tail cursor is set to -1, the
cursor is incremented to indicate the next available position in the queue and a new arrival is inserted
into the array at the location indicated by the cursor.

Q: What happens when an item is removed from the queue?


A: In a Bank, when a customer is finished at the service desk, the remaining customers move up one
position in the queue. Assuming that a queue is implemented as an array, we can define the following
basic operations and use them whenever needed in the algorithm.

• Queue(0) always contains the first element in the queue.


• Initially tail=-1
Procedure ENQUEUE(item, queue, n, tail)
//Insert item into the queue represented in queue(0:n-1)//
if tail ≥ n-1 then report QUEUE_FULL;
else
tail= tail +1;
queue(tail) = item ;
end ENQUEUE

Procedure DEQUEUE (item, queue, tail)


//delete an item from a queue unless queue is empty //
if tail < 0 then report QUEUE_EMPTY;
else
for i=1 to tail-1
queue(i-1) = queue(i);
tail = tail-1;
end DEQUEUE
enqueue(‘l’) dequeue()
tail
tail tail
n-1 -
n-1 -
n-1 -
n-2 -
n-2 -
n-2 -
... ... ... ...
... ...
i+1 - i+1 l
i+1 -
i k i k
i l
... ... ... ...
... ...
2 c 2 c
2 d
1 b 1 b
1 c
0 a 0 a
0 b

head head
head

You can also writ e a function which returns the element at the front of the queue without deleting it or
test functions.
CSE211 Lecture Notes – 2004/2005-II

This above operation is costly. After each dequeue operations all elements need to be moved by one
position.

What else we can do?

We can define a head position and increment it by one whenever an item is deleted.

The enqueue operation will remain the same but dequeue algorithm will be as follows

• Initially, head=0, tail=-1


• The number of elements in the queue is tail - head + 1
Procedure DEQUEUE (item, queue, head, tail)
//delete an item from a queue unless queue is empty //

if tail < head then report QUEUE_EMPTY


else
item = queue (head)
head = head +1
end DEQUEUE

tail tail
n-1 - n -1 -
n-2 - n -2 -
... ...
dequeue() ... ...
i+1 l
i+1 l
i k
i k
... ...
... ...
2 c
2 c
1 b
1 b
0 a
0 a

head head
This scheme works until the tail cursor reaches the upper limit of the array, at which time it breaks
down since no new elements can be enqueued. Although the queue is not full as the elements being
dequeued we have a problem. We need to find a way to discover the available space.

One solution: Reorganize the queue whenever the tail cursor reached the end of the array: Move the
element at the head to the first array position and move the others up behind it. This will require time
proportional to the queue length but the operation will be done less frequently.

More elegant solution: A self regulating solution is to treat the array as though the last position is
glued back to the first position (another words circular). The tail cursor would wrap around using
empty space at the beginning of the array for new arrivals (the space that was vacated by previous
departures)
CSE211 Lecture Notes – 2004/2005-II

2. Circular Queues
A more efficient queue representation is obtained by regarding the array QUEUE(0:n-1) as circular.
When rear=n-1 the next element entered at QUEUE(0) in case that slot is free. In order to add an item,
it will be necessary to move tail one position clockwise. Similarly, it will be necessary to move head
one position clockwise when a deletion is made.
n-1
tail 0
n-1 - a
n-2 -
1
...
i+1
...
l
b
i
...
k
...
head 1
2
1
c
b
tail i
0 a
k l

head i
The queue is genuinely full whenever the tail cursor catches up to the head cursor

2.1. Array Implementation

If tail = n-1 then tail= 0


else tail = tail + 1

using the modula operator which computes remainders, this is just


tail= (tail +1) mod n.

Also using modula operation deletion is just


head = (head+ 1) mod n.

If you examine the following algorithms you will see that addition and deletion is carried out in a fixed
amount of time or O(1).

Initially, head=tail=n-1;

Convention: Head shows the position (array index) immediately preceding the first element of the
queue rather than the index of the first element.
Empty Condition: Last element of array precedes the first element within queue. Since
head=tail queue is initially empty.

SEE THE EXAMPLES GIVEN IN THE CLASS

Correctness Constraint: Allow queue to grow only as large as one less than the size of the array. If
array size is n then max number of elements in the queue is n-1.
CSE211 Lecture Notes – 2004/2005-II

Procedure CQ_enqueue (item, queue, head, tail)


//Insert item into the circular queue represented in Q(0:n-1); rear
points to the last item and front is one position counterclockwise from the
first item in queue //
tail = (tail+1) mod n;
if tail = head then report QUEUE_FULL;
else queue (tail) = item;
end CQ_enqueue

Procedure CQ_dequeue (item, queue , head, tail)


//removes the front element of queue //

if head = tail then report QUEUE_EMPTY;


else head = (head + 1) mod n;
item = queue(head);
end CQ_dequeue

Note that if the QUEUE is declared as (1:n) then initially head = tail = n

Home Exercise: You can separate the function, which returns the first item in the queue from the
delete operation.

3. Priority Queues
The priority queue is a data structure in which intrinsic ordering of the elements determines the results
of its basic operations.

An ascending priority queue is a collection of items into which items can be inserted arbitrarily and
from which only the smallest item can be removed. On the other hand a descending priority queue
allows only the largest item to be removed.

Home Exercise: Develop an ADT specification for priority queue.

Potrebbero piacerti anche