Queue
What is a queue? Queues have two ends: It is an ordered group of homogeneous items, examples: The cars at a stop light, The check-out line at a grocery store Queues have two ends: Items are added at one end. Items are removed from the other end. FIFO property: First In, First Out The item added first is also removed first
Conceptual View of a Queue Adding an element Front of queue New element is added to the rear of the queue
Conceptual View of a Queue Removing an element New front element of queue Element is removed from the front of the queue
Uses of Queues in Computing For any kind of problem involving FIFO data Printer queue Keyboard input buffer GUI event queue (click on buttons, menu items)
Uses of Queues in Computing In simulation studies, where the goal is to reduce waiting times: Optimize the flow of traffic at a traffic light Determine number of cashiers to have on duty at a grocery store at different times of day Ticket counter simulation
Queue Operations enqueue : add an element to the tail of a queue dequeue : remove an element from the head of a queue front : examine the element at the head of the queue (“peek”) Other useful operations (e.g. is the queue empty) It is not legal to access the elements in the middle of the queue!
Array Implementation of a Queue First Approach: Use an array in which index 0 represents one end of the queue (the front) Integer value last represents the last occupied slot in the array (the number of elements currently in the queue will be last + 1) Discussion: What is the challenge with this approach?
Operations on a Queue Operation Description dequeue enqueue front Removes an element from the front of the queue enqueue Adds an element to the rear of the queue front Examines the element at the front of the queue isEmpty Determines whether the queue is empty size Determines the number of elements in the queue isFull Determines whether the queue is full
An Array Implementation of a Queue A queue aq containing four elements first 1 2 3 4 … queueArray aq 3 last
Queue After Adding an Element last is incremented, Element is added at the array location given by the new last first 1 2 3 4 … queueArray aq 4 last
Queue After Removing an Element Element is removed from array location 0, remaining elements are shifted forward one position in the array, and then last is decremented. 1 2 3 4 … queueArray aq 3 last
Operations on a Queue Operation Description dequeue enqueue front Removes an element from the front of the queue enqueue Adds an element to the rear of the queue front Examines the element at the front of the queue isEmpty Determines whether the queue is empty size Determines the number of elements in the queue isFull Determines whether the queue is full
Second Approach: Queue as a Circular Array If we don't fix one end of the queue at index 0, we won't have to shift elements Circular array is an array that conceptually loops around on itself The last index is thought to “precede” index 0 In an array whose last index is n, the location “before” index 0 is index n; the location “after” index n is index 0 Need to keep track of where the first as well as the last of the queue are at any given time
Conceptual Example of a Circular Queue first After 5 dequeues 1 1 After 7 enqueues first 12 12 11 last 11 last 10 10 last 1 first 12 11 After 8 more enqueues 10
Circular Array Implementation of a Queue 3 2 3 4 1 first queueArray 5 cq 7 5 6 n-1 last currentsize n-2 7 n-3 8 . 9 . 10 .
A Queue Straddling the End of a Circular Array 98 2 3 4 1 first queueArray 5 cq 1 4 6 99 last currentSize 98 7 97 8 . 9 . 10 .
Circular Queue Drawn Linearly Queue from previous slide 98 cq first queueArray 1 2 3 4 96 97 98 99 … 1 4 last currentSize
Circular Array Implementation When an element is enqueued, the value of last is incremented But it must take into account the need to loop back to index 0: last = (last+1) % queue’sLength; Yes, so it may need enlarging
#ifndef INT_QUEUE_H_INCLUDED #define INT_QUEUE_H_INCLUDED class intQueue { private: int currentsize, arraysize, first, last; int *queueArray; public: intQueue(int s = 100); // Constructor ~intQueue(); // Destructor intQueue(const intQueue& other); // Copy Constructor intQueue& operator=(const intQueue& other); // Assignment operator bool enqueue(int); // Add to end bool dequeue(); // Remove from front int front() const; // Get value at front bool isEmpty() const { return currentsize <= 0; } bool isFull() const { return currentsize >= arraysize; } int Size() const { return currentsize; } }; #endif // INT_QUEUE_H_INCLUDED
#include "intQueue.h" #include <iostream> #include <cstdlib> using namespace std; intQueue::intQueue(int s) // Constructor { queueArray = new int[s]; // Dynamically allocate array arraysize = s; currentsize = 0; first = 0; last = -1; } intQueue::~intQueue() // Destructor delete[] queueArray; // Deallocate array
intQueue::intQueue(const intQueue& other) // Copy Constructor { arraysize = other.arraysize; currentsize = other.currentsize; first = other.first; last = other.last; queueArray = new int[arraysize]; // Dynamically allocate array for (int i=0; i<arraysize; i++) // Copy array contents queueArray[i] = other.queueArray[i]; } intQueue& intQueue::operator=(const intQueue& rhs) if (this == &rhs) return *this; // handle self assignment arraysize = rhs.arraysize; currentsize = rhs.currentsize; first = rhs.first; last = rhs.last; delete [] queueArray; // Deallocate old array queueArray = new int[arraysize]; // Dynamically allocate new one for (int i=0; i<arraysize; i++) // Copy array contents queueArray[i] = rhs.queueArray[i]; return *this;
bool intQueue::enqueue(int value) { if (currentsize >= arraysize) return false; last = (last + 1) % arraysize; queueArray[last] = value; currentsize++; return true; } bool intQueue::dequeue() if (currentsize < 1) return false; first = (first + 1) % arraysize; currentsize--; int intQueue::front() const if (currentsize < 1) cout << "Cannot take front of empty queue!\n"; exit(0); return queueArray[first];