View
218
Download
0
Category
Preview:
DESCRIPTION
3 Introduction to Queues In real life, a queue is a waiting line. A line of people waiting for a bank teller A line of cars at a toll both "This is the captain, we're 5 th in line for takeoff"
Citation preview
1
Queues
Chapter 4
2
Objectives
You will be able to Describe a queue as an ADT. Build a dynamic array based
implementation of a queue ADT.
3
Introduction to Queues
In real life, a queue is a waiting line. A line of people waiting for a bank teller A line of cars at a toll both "This is the captain, we're 5th in line for
takeoff"
4
The Queue As an ADT
In programming, a queue is a sequence of data elements.
In the sequence Items can be removed only at the front. Items can be added only at the back. Referred to as a “First In First Out” or FIFO
container. Also called “First Come First Serverd” or FCFS.
A stack is a “Last In First Out” or LIFO container.
5
The Queue As an ADT
Basic operations Construct a queue Check if empty Check if full Enqueue (add element to back) Dequeue (remove element from front and
return it) Front (retrieve value of element from front) Clear (remove all elements)
6
Variations of the Queue ADT
Double ended queue, Deque Pronounced “deck” Permits items to be inserted and removed at
either end.
Priority Queue Multiple priority levels Items can be inserted at the end of any level.
7
The Queue As an ADT
Most of what you have learned about stacks applies to queues. Dynamic array based implementation. Linked list implementation.
We will look at one other version. Multiple queues in a single array. A form of linked list implementation.
8
Array Based Implementations
All array based implementations have: Head Index
“first” in examples in the book. Often called the “taker” Index of oldest element in the queue.
The one to be removed next.
First Free Index Often called the “putter” Where the next element will be added.
If taker == putter, queue is empty.
9
Array Based Implementations
The putter advances down the array and back to the top. Circular buffer.
The taker follows the putter down the array (and back around to the top.)
If the putter catches up with the taker, the queue is full.
If the taker catches up with the putter, the queue is empty.
10
Empty and Full Conditions
If putter == taker, is the queue full or empty?
We need a rule to distinguish the two conditions.
The rule: When putter == taker, the queue is
empty.
11
Empty and Full Conditions
Implications of the rule: We can’t put an element into the
postion just before the taker. Otherwise the queue would appear to be
empty when it is acutally full. There will always be at least one empty
element in the array. Actual capacity of the queue is one less
than the size of the array.
12
Empty and Full Conditions
putter == taker Queue is empty. OK to put. Not OK to take.
putter + 1 mod array_size = taker Queue is full OK to take. Not OK to put.
13
Queue Example
Create new empty C++ console project. Queue_Demo
Add Queue.h Add Queue_Test.cpp
Initially "Hello, world!"
14
Queue_Test.cpp
Initial stub:
#include <iostream>
using namespace std;
int main(void){ cout << "This is Stack Demo\n";
cin.get(); return 0;}
15
Queue Template
#pragma once#include <iostream>#include <cassert>
template <class T>class Queue{public: Queue(size_t capacity = 1000); ~Queue(); bool IsEmpty() const; bool IsFull() const;
// Add a value to the end of the Queue. void Enqueue(const T& value);
// Remove and return value at front of Queue. T Dequeue();
// Retrieve value at front of Queue without removing it. T Front() const;
16
Queue.h
// Display Queue contents. void Display(std::ostream& out) const;
void Clear();
private: T* data; size_t size; size_t putter; size_t taker;};
17
Constructor and Destructor
template <class T>Queue<T>::Queue(size_t capacity){ size = capacity+1; data = new T[size]; assert (data != 0); putter = 0; taker = 0;}
template <class T>Queue<T>::~Queue(){ delete[] data;}
18
IsEmpty and IsFull
template <class T>bool Queue<T>::IsEmpty() const{ return putter == taker;}
template <class T>bool Queue<T>::IsFull() const{ return taker == ((putter+1) % size);}
19
Enqueue
template <class T>void Queue<T>::Enqueue(const T& value){ if (this->IsFull()) { throw "Attempt to add to full queue"; }
data[putter] = value; putter = (++putter) % size;}
20
Dequeue
template <class T>T Queue<T>::Dequeue(){ if (this->IsEmpty()) { throw "Dequeue called for empty Queue"; } T temp = data[taker]; taker = (++taker) % size; return temp;}
21
Front
template <class T>T Queue<T>::Front() const{ if (this->IsEmpty()) { throw "Front of empty Queue requested"; }
return data[taker];}
22
Display
template <class T>void Queue<T>::Display(std::ostream& out) const{ for (int i = taker; i != putter; i = (i + 1)%size) { out << data[i] << endl; }}
23
Create Queue_Test.cpp
Update Stack_Test.cpp to be Queue_Test.cpp
Download to project folder: http://www.cse.usf.edu/~turnerr/Data_Structures/Downloads/2011_02_07
_Stacks/ File stack_test.cpp.txt
24
Queue_Test.cpp
#include <iostream>#include "Queue.h" #include <cassert>
using namespace std;
const int QUEUE_CAPACITY = 10;
int main(){ Queue<int> q(QUEUE_CAPACITY); assert (q.IsEmpty()); cout << "Newly created queue is empty\n";
printf ("Enqueueing 0 - %d \n", QUEUE_CAPACITY - 1); for (int i = 0; i < QUEUE_CAPACITY; ++i) { q.Enqueue(i); }
25
Queue_Test.cpp
cout << "Initial queue:\n"; q.Display(cout);
assert(!q.IsEmpty()); cout << "Now the queue is not empty\n";
cout << "Adding one more element, which should cause overflow. " << endl; try { q.Enqueue(1); cout << "ERROR\n"; // Should have thrown exception } catch (const char* msg) { cout << "Attempt to overfill queue threw exception as expected\n"; cout << "Message: " << msg << endl; }
cout << "Queue should be unchanged\n" << endl; q.Display(cout);
26
Queue_Test.cpp
cout << "Now removing elements from the queue\n"; while (!q.IsEmpty()) { int front = q.Front(); cout << "queue head: " << front << endl; int next_item = q.Dequeue(); assert (next_item == front); }
cout << "Queue is now empty\n";
27
Queue_Test.cpp
cout << "Getting front of empty queue. This should fail\n"; try { int x = q.Front(); cout << "ERROR\n"; // Should have thrown exception } catch (const char* msg) { cout << "Attempt to get front of empty queue threw exception as expected\n"; cout << "Message: " << msg << endl; }
28
Queue_Test.cpp
cout << "Doing one more Dequeue. This should fail\n"; try { q.Dequeue(); cout << "ERROR\n"; // Should have thrown exception cin.get(); } catch (char* msg) { cout << "Attempt to Dequeue empty queue threw exception as expected\n"; cout << "Message: " << msg << endl; }
29
Queue_Test.cpp
cout << "Testing dynamic allocation\n";Queue<int>* q2 = new Queue<int>(QUEUE_CAPACITY);assert(q2 != 0);cout << "Allocation was successful\n";cout << "Testing delete\n";delete(q2);q2 = 0;cout << "Delete was successful\n";
cout << "Test complete. Press Enter to exit." << endl;cin.get(); // Hold window openreturn 0;
30
Program Running
31
Program Running
Recommended