// ******************************************************************* // Last Revised: September 1, 1997 // // APCS queue class IMPLEMENTATION // // queue implemented using the APCS vector class // based on queue class in Mark Weiss' : Algorithms, Data Structures, // and Problem Solving with C++ // ******************************************************************* #include "apqueue.h" #include const int QDEFAULT_SIZE = 10; // default initial queue size template apqueue::apqueue() : mySize(0), myFront(0), myBack( -1 ), myElements(QDEFAULT_SIZE) // postcondition: the queue is empty { } template apqueue::apqueue(const apqueue & q) : mySize(q.mySize), myFront(q.myFront), myBack(q.myBack), myElements(q.myElements) // postcondition: queue is a copy of q { } template apqueue::~apqueue() // postcondition: queue is destroyed { // vector destructor takes care of memory } template const apqueue & apqueue::operator=(const apqueue & rhs) // postcondition: normal assignment via copying has been performed { if( this != &rhs) { mySize = rhs.mySize; // copy all fields of rhs myElements.resize(rhs.myElements.length()); // resize storage myFront = 0; myBack = mySize - 1; // index from 0 .. mySize - 1 int k; int rhsk = rhs.myFront; for(k=0; k < mySize; k++) { myElements[k] = rhs.myElements[rhsk]; Increment(rhsk); } } return *this; } template const itemType & apqueue::front() const // precondition: queue is [e1, e2, ..., en] with n >= 1 // postcondition: returns e1 { return myElements[myFront]; } template bool apqueue::isEmpty() const // postcondition: returns true if queue is empty, false otherwise { return mySize == 0; } template int apqueue::length() const // precondition: queue is [e1, e2, ..., en] with n >= 0 // postcondition: returns n { return mySize; } template void apqueue::enqueue(const itemType & item) // precondition: queue is [e1, e2, ..., en] with n >= 0 // postcondition: queue is [e1, e2, ..., en, item] { if (mySize >= myElements.length()) // grow if necessary to add element { DoubleQueue(); } Increment(myBack); // add element at back of queue myElements[myBack] = item; mySize++; } template void apqueue::dequeue() // precondition: queue is [e1, e2, ..., en] with n >= 1 // postconditions: queue is [e2, ..., en] and item == e1 { if (isEmpty()) { cerr << "dequeue from empty queue" << endl; abort(); } mySize--; // one fewer element Increment(myFront); } template void apqueue::dequeue(itemType & item) // precondition: queue is [e1, e2, ..., en] with n >= 1 // postcondition: queue is [e2, ..., en] and item == e1 { if (isEmpty()) { cerr << "dequeue from empty queue" << endl; abort(); } item = myElements[myFront]; mySize--; // one fewer element Increment(myFront); } template void apqueue::makeEmpty() // postcondition: queue is empty { mySize = 0; myFront = 0; myBack = -1; } template void apqueue::Increment( int & val ) const // postcondition: val increased by one relative to size of myElements // i.e., wraps to 0 after reaching capacity of vector storage { val++; if (val >= myElements.length() ) { val = 0; } } template void apqueue::DoubleQueue() // precondition: queue = e1, e2, ..., en, size = n, capacity = m // postcondition: queue = e1, e2, ..., en, size = n, capacity = 2*m { // this could be made more efficient by doing the copy // in place (without the temporary vector temp) apvector temp(myElements.length()*2); // new storage int j,k=myFront; // copy to 0.. for(j=0; j < mySize; j++) { temp[j] = myElements[k]; Increment(k); } myElements = temp; // reset private vars to mirror new storage myFront = 0; myBack = mySize-1; }