260 likes | 477 Views
Queues. Chapter 5. Queue Definition. A queue is an ordered collection of data items such that: Items can be removed only at one end (the front of the queue) Items can be added only at the other end (the back of the queue). Basic Operations. construct a queue (usually empty)
E N D
Queues Chapter 5
Queue Definition • A queue is an ordered collection of data items such that: • Items can be removed only at one end(the front of the queue) • Items can be added only at the other end(the back of the queue)
Basic Operations • construct a queue (usually empty) • empty Check if queue is empty • addQ Add an item to back of queue • front Retrieve element at front of queue • RemoveQ Remove element at front of queue
for (;;) { while ( printerQueue.empty()) sleep 1; printFile = printerQueue.removeQ(); Print( printFile); } Queue FAQs • A queue is a FIFO structureFirst-In First-Out • Examples of queues • I/O buffers (stream of bytes from keyboard) • Scheduling queues in a multiuser OS • Printer queue
Scheduling Queues • Resident queue • on disk waiting formemory • Ready queue • in memory, onlyneeds CPU to run • Suspended queue • waiting for I/O transfer or to be reassigned to the CPU
Interesting Application Evaluate If A String Is A Palindrome This code will not do what it claims. Do a white box test of the code.
Implementation with An Array Requirements • Array space for storage for the data • A pointer to indicate the front of the queue • A pointer to indicate the back of the queue • Structures would includeitemType myQueue [queueQuantity];int myFront, myBack;
myBack myFront Implementation with An Array • Additions to the queue • place new element where back points, increment myBack • Deletions from the queue • increment myFront • What problems can you see with this? myQueue
Implementation with An Array • Obviously we would run out of space • Possible solutions • Shifting the array elements downward with each deletion • 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 array • Given itemType myQueue [queueQuantity];int myFront, myBack; • When myBack (or myFront) hits the end of myQueue, it should wrap around to the beginningmyBback = (myBack + 1) % queueQuantity;
"Circular" Array-Implementation • Initially queue is emptymyFront = myBack = 0; • How do we know queue is empty at any time?? • myFront== myBack • What would happen if array fills up … what would be value of myFront and myBack? • they would be the same … why? • So … how to tell empty from full??
"Circular" Array-Implementation Common solutions • Keep an empty slot between myFront and myBack • declare array asitemType myQueue [queueQuantity +1]; • Keep an auxiliary counter to track actual number of elements in queue
Queue Class Specification # ifndef QUEUE # define QUEUE Note again, capacity and element type declared outside class. 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” QueueElement removeQ(); // retrieve and remove /***** Data Members *****/ private: QueueElement myArray [QUEUE_CAPACITY]; int myFront, myBack; }; // end of class declaration # endif
Queue Class Implementation • Use the class declaration to write the implementation • Also write a driver to test the implementation • It should • instantiate multiple queues • test for empty, full • add, remove, and look at the front element • enter values from keyboard, from file • print output of queue to screen, to file
Linked List Implementation • Interface would remain the same • empty(), full(), front(), addQ(), removeQ() • The storage structure would be a linked list. • The markers would be pointers • instead of indices into an array • myFront contains pointer to first node • myBack contains pointer to last node
Linked List Implementation • empty • returns true if myFront points to NULL • addQ • allocates new node • link it off myBack • update myBack • removeQ • remove and return first element • update myFront
Linked List Implementation • front • returns value of node where myFront points to • full??? • returns true if myFront = = myBack • Write specification and implementation as an exercise
Dequeue • Double-ended-queue • Similar to a queue • But … additions and deletions can occurat either end • Methods must have • either a parameter specifying at which end the action should occur • or multiple methods (functions) provided
addQ( ) Example for Dequeue Version with parameter for where addition takes place
Multiple Method Version void Deque::push_front( int item) { if (( myBack +1)% QUEUE_CAPACITY == myFront) cout << "FULL, cannot add to queue." << endl; // enqueue at front else { 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; // regular enqueuing else { myArray[ myBack] = item; myBack = ( myBack+ 1) % QUEUE_CAPACITY; } return; }
Comments on deque • A standard container provided by the STL • Easily implemented by the vector type • More coming in Chapter 6
Priority Queues • Definition : A queue where the order of the elements … • is by some priority • rather than by the order in which they are received • Any queue implementation can be used • Only the addQ() method must be altered • Element is not added at back • Queue must be scanned for correct location for insertion
Priority Queues • What would be the drawback of using an implementation that used arrays? • shifting elements • Hence a linked list implementation is preferred
Priority Queues What changes would be made to this to use a linked list version?