0% found this document useful (0 votes)
222 views23 pages

Queues

The document discusses different types of queues including regular queues, priority queues, and deques. It defines queues as FIFO data structures where items can only be removed from the front and added to the back. It provides examples of queue applications like print queues and CPU scheduling. It also compares queues to stacks and describes different implementations of queues using arrays and linked lists. Priority queues require scanning the queue to insert items in priority order. Deques allow additions and removals from either end.
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
222 views23 pages

Queues

The document discusses different types of queues including regular queues, priority queues, and deques. It defines queues as FIFO data structures where items can only be removed from the front and added to the back. It provides examples of queue applications like print queues and CPU scheduling. It also compares queues to stacks and describes different implementations of queues using arrays and linked lists. Priority queues require scanning the queue to insert items in priority order. Deques allow additions and removals from either end.
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 23

Chapter 5: Queues

Defn. As a data structure, a queue is an ordered collection of data items with the property that items can be removed only at one end, called the front of the queue, and items can be added only at the other end, called the back of the queue. Basic operations are: Queue: Front: Remove ONLY Back: Add ONLY construct: Create an empty queue empty: Check if a queue is empty addQ: Add a value at the back of the queue front: Retrieve the value at the front of the queue removeQ: Remove the value at the front of the queue Whereas a stack is a Last-In-First-Out (LIFO) structure, a queue is a First-In-First-Out (FIFO) or First-Come-First-Served (FCFS) structure.

Examples:
a. I/O buffers: queues, scrolls, deques From a file: (queue)
Disk Memory

Input Buffer queues input for the CPU

Input Buffer

CPU

X Infile >> X;

Interactively: (scroll queue on one end, stack on the other)


Scroll:

Keyboard

Front: Remove ONLY Back: Add or Remove (Backspace)

Memory
Backspace

Input Buffer cin >> X;

Screen handling: (deque doubleended queue)


Scroll: Front: Remove or Add Back: Add or Remove

b. Scheduling queues in a multi-user computer system:


Printer queue: When files are submitted to a printer, they are placed in the printer queue. The printer software executes an algorithm something like: for (;;) { while (printerQueue.empty()) sleep 1; printFile = printerQueue.removeQ(); Print(printFile); }

Other Queues:
1. Resident queue: 2. Ready queue:

3. Suspended queue:

On disk, waiting for memory In memory has everything it needs to run, except the CPU Waiting for I/O transfer or to be reassigned the CPU

1 2

c. CPU Scheduling:
Probably uses a priority queue: Items with lower priority are behind all those with higher priority. (Usually a new item is inserted behind those with the same priority.)

Queues vs. Stacks


Stacks are a LIFO container Store data in the reverse of order received Queues are a FIFO container Store data in the order received Stacks then suggest applications where some sort of reversal or unwinding is desired. Queues suggest applications where service is to be rendered relative to order received. Stacks and Queues can be used in conjunction to compare different orderings of the same data set. From an ordering perspective, then, Queues are the opposite of stacks Easy solution to the palindrome problem

Easy Palindrome Check


#include Stack.h; #include Queue.h; #include <iostream.h> using namespace std; int main(){ Stack S; Queue Q; char ch; cout << Enter string to be tested as palindrome: ; while (cin >> ch){ S.push(ch); Q.addq(ch); } bool pal = true; while (!Q.empty() && pal) { pal = Q.front() == S.pop(); Q.removeq(); } if (pal) cout << Palindrome!! << endl; return 0;

Array Implementation
Any implementation of a queue requires: storage for the data as well as markers (pointers) for the front and for the back of the queue. An array-based implementation would need structures like myArray, an array to store the elements of the queue myFront, an index to track the front queue element myBack, an index to track the position following last queue element

Additions to the queue would result in incrementing myBack. Deletions from the queue would result in incrementing myFront. Clearly, wed run out of space soon! Solutions include: Shifting the elements downward with each deletion (YUCK!!) Viewing array as a circular buffer, i.e. wrapping the end to the front

Circular Array-Implementation
Wraparound keeps the addition/deletion cycle from walking off the edge of the storage array.

Say, myArray has QUEUE_CAPACITY elements.


When myBack hits the end of myArray, a deletion should wrap myBack around to the first element of myArray, viz:

myBack++; if (myBack = = QUEUE_CAPACITY) myBack = 0;


//equivalently (preferred, concise) myBack = (myBack + 1) % QUEUE_CAPACITY; Analogous handling of myFront needed.

Circular Array-Implementation II
myBack: myFront:

Incremented when an item is ADDED Incremented when an item is REMOVED

Initially, a queue object is empty. myFront = = 0 myBack = = 0 After many insertions and deletions, the queue is full First element, say, at myArray[i] myFront has value of i. Last element then at myArray[i-1] (i > 0) myBack has value of i. PROBLEM: How to distinguish between empty & full??? Some Common Solutions: 1. Keep an empty slot between myFront and myBack, i.e., myArray uses QUEUE_CAPACITY - 1 elements 2. Keep an integer counter to track actual number of elements in queue 3. Keep a boolean full variable to keep track of if queue is full or not

QUEUE class
#ifndef QUEUE #define QUEUE const int QUEUE_CAPACITY = 128; typedef int QueueElement; class Queue { /***** Function Members *****/ public: Queue(); bool empty() const; bool full() const; void addQ(const QueueElement & value); QueueElement front const(); //nondestructive peek void removeQ(); /***** Data Members *****/ private: QueueElement myArray[QUEUE_CAPACITY]; int myFront, myBack; }; // end of class declaration #endif

QUEUE class implementation


Queue::Queue() { myFront = myBack = 0; } bool Queue::empty() { return myFront == myBack; } bool Queue::full() { return myFront == (myBack + 1) % QUEUE_CAPACITY; }

QUEUE class implementation II


void Queue::addQ(const QueueElement& value) { if (myFront != (myBack + 1) % QUEUE_CAPACITY) { myArray[myBack] = value; myBack = (myBack + 1) % QUEUE_CAPACITY; } return; } void Queue::removeQ() { myFront = (myFront + 1) % QUEUE_CAPACITY; }

Linked list implementation


Linked list implementation is another approach for queue representation. The interface to the class Queue empty, addq, removeq, front, etc. would not change The storage structure would be a linked list. The markers would be pointers now rather than indices into an array. myFront would contain the address of the first node in this list myBack would contain the address of the last node in this list empty would test if myFront was a nonnull pointer, addq would allocate a new node, link it off myBack and update myBack, removeq would remove the first element and update myFront, front would return a copy of the element whose address was in myFront

Deque
A deque (double-ended queue) is similar to a queue BUT additions and deletions may be performed on either end. Hence, an implementation needs a directive (tag) indicating at what end the operation is to be performed OR multiple methods should be provided. We modify a queue's circular array implementation here. #include <iostream> using namespace std; enum where {front, rear};

/* Deque implemented with same data members myArray myFront myBack Constructors and empty(), full() methods the same */

Deque enqueuing
void Deque::addQ(int item, where w) { if ((myBack +1)% QUEUE_CAPACITY == myFront) cout << "FULL, cannot add to queue. Error!! " << endl; else if (w == rear) // regular enqueuing { myArray[myBack] = item; myBack = (myBack+ 1) % QUEUE_CAPACITY; } else // enqueue at front { if (!myFront) myFront = QUEUE_CAPACITY; else myFront--; myArray[myFront] = item; } return; }

Deque enqueuing
//better to provide two addition methods void Deque::push_front(int item) {if ((myBack +1)% QUEUE_CAPACITY == myFront) cout << "FULL, cannot add to queue." << endl; else // enqueue at front { if (!myFront) myFront = QUEUE_CAPACITY; else myFront--; myArray[myFront] = item; } return; } void Deque::push_back(int item) { if ((myBack +1)% QUEUE_CAPACITY == myFront) cout << "FULL, cannot add to queue." << endl; else // regular enqueuing { myArray[myBack] = item; myBack = (myBack+ 1) % QUEUE_CAPACITY; } return; }

Deque dequeuing
int Deque::pop_front() // assume non-empty { int item = myArray[myFront]; myFront= (myFront+ 1) % QUEUE_CAPACITY; return item; } void Deque::pop_back() // assume non-empty { if (!myBack) myBack = QUEUE_CAPACITY; else myBack--; int item = myArray[myBack]; // dequeue from rear return item; }

deques
The deque is a standard container provided by STL.

It is easily implemented by the vector type.

See chapter 6 for more details.

Priority Queues
Priority queues are queues in which items are ordered by priority rather than temporally (i.e. order in which received). Any queue implementation then can be taken and modified to acquire a priority queue. The only needed modification is the addq() method. Instead of unconditionally adding to the back, the queue must be scanned for the correct insertion point. An array implementation then would require shifting elements (YUCK). Hence a linked list implementation is preferred. (Develop then the preferred solution after chapter 8)

Priority Queues
class PriorityQ { public: PriorityQ(); void addq(int); int removeq(); bool empty(); bool full(); int back(); int size(); private: const int PRIORITYQ_CAPACITY = some_value; int myArray[PRIORITYQ_CAPACITY]; int myFront; int myBack; };

You might also like