//================================================================== // File: queue.h // Author: Timothy A. Budd // Platform: Cfront // Description: Template Description of Abstract Queue ADT // Copyright (c) 1992 by Timothy A. Budd, All Rights Reserved // Permission granted for duplication if not for profit //================================================================== # ifndef queueH # define queueH template class queue { public: // protocol for queue operations virtual void deleteAllValues () = 0; virtual T dequeue () = 0; virtual void enqueue (T value) = 0; virtual T front () const = 0; virtual int isEmpty () const = 0; }; # include "vector.h" template class queueVector : public queue { public: // constructor requires a starting size queueVector(unsigned int max); queueVector(const queueVector & x); // implement queue protocol virtual void deleteAllValues (); virtual T dequeue (); virtual void enqueue (T value); virtual T front () const; virtual int isEmpty () const; private: vector data; const unsigned int max; unsigned int nextSlot; unsigned int nextUse; }; # include "list.h" // // class queueList // queue implemented using list operations // template class queueList : public queue { public: // constructors queueList(); queueList(const queueList & v); // protocol for queue operations virtual void deleteAllValues (); virtual T dequeue (); virtual void enqueue (T value); virtual T front () const; virtual int isEmpty () const; private: doubleEndedList data; }; //================================================================== # include template queueVector::queueVector(unsigned int size) : max(size), data(size) { // make sure queue is initially empty deleteAllValues(); } template queueVector::queueVector(const queueVector & v) : data(v.data), max(v.max), nextSlot(v.nextSlot), nextUse(v.nextUse) { // no further initialization } template void queueVector::deleteAllValues() { nextSlot = 0; nextUse = 0; } template void queueVector::enqueue(T val) { data[nextSlot++] = val; if (nextSlot >= max) nextSlot = 0; // make sure queue has not overflowed assert(nextSlot != nextUse); } template T queueVector::front() const { // can not return a value from an empty queue assert(! isEmpty()); return data[nextUse]; } template T queueVector::dequeue() { // can not dequeue from an empty queue assert(! isEmpty()); int dataloc = nextUse; nextUse++; if (nextUse >= max) nextUse = 0; return data[dataloc]; } template int queueVector::isEmpty() const { // queue is empty if next slot is // pointing to same location as next use return nextSlot == nextUse; } //================================================================== template queueList::queueList() : data() { // no further initialization } template queueList::queueList(const queueList & v) : data(v.data) { // no further initialization } template void queueList::deleteAllValues() { data.deleteAllValues(); } template void queueList::enqueue(T value) { data.addToEnd(value); } template T queueList::front() const { return data.firstElement(); } template int queueList::isEmpty() const { return data.isEmpty(); } template T queueList::dequeue() { T result = data.firstElement(); data.removeFirst(); return result; } // // class queueRingBuffer - // implementation of queue // using ring buffers // template class queueRingBuffer : public queue { public: // constructor takes initial size queueRingBuffer(unsigned int); ~queueRingBuffer(); // protocol for queue operations virtual void deleteAllValues (); virtual T dequeue (); virtual void enqueue (T value); virtual T front () /* const */; virtual int isEmpty () /* const */; private: BuddLink * lastFilled; BuddLink * lastFree; }; template inline void queueRingBuffer::deleteAllValues() { lastFree = lastFilled; } template inline int queueRingBuffer::isEmpty() /* const */ { // queue is empty if pointers are equal return lastFree == lastFilled; } template queueRingBuffer::~queueRingBuffer() { BuddLink * p = lastFree; BuddLink * next; // walk around the circle deleting nodes while (p->ptrToNextLink != lastFree) { next = p->ptrToNextLink; delete p; p = next; } } template queueRingBuffer::queueRingBuffer(unsigned int max) { // create the first link T initialvalue; lastFree = new BuddLink(initialvalue, 0); assert(lastFree != 0); lastFilled = lastFree; // make value point to itself lastFilled->ptrToNextLink = lastFilled; // now add the remainder of the elements while (max-- > 0) lastFilled->insert(initialvalue); } template T queueRingBuffer::dequeue() { // cannot dequeue from empty queue assert(! isEmpty()); // advance last free position lastFree = lastFree->ptrToNextLink; // return value stored in last free position return lastFree->value; } template T queueRingBuffer::front() /* const */ { // cannot take front of empty queue assert(! isEmpty()); BuddLink * ptrToFront = lastFree->ptrToNextLink; return ptrToFront->value; } template void queueRingBuffer::enqueue(T val) { // first check for potential overflow if (lastFilled->ptrToNextLink == lastFree) lastFilled = lastFilled->insert(val); else { // simply advance the last filled pointer lastFilled = lastFilled->ptrToNextLink; lastFilled->value = val; } } # endif