//--------------------------------------------------------------------------//
// file: queue.h //
// --this is a header file for my implementation of a template queue //
// class based off list.h //
// Christopher J. Dickey //
// 2/12/96 //
//--------------------------------------------------------------------------//
#include "queue.h"
//------------------------------------queueClass-----------------------------//
template <class T>
class queueClass : public listClass
{
public:
queueClass() : head(NULL), tail(NULL), num_items(0) {}
queueClass(const queueClass<T>& Q);
~queueClass();
// Enqueue and dequeue add and remove items from the queue, they do NOT
// however free up or create the item--that's left up to the coder
virtual bool AddItem(nodeStruct<T> *node, T* item);
virtual bool RemoveItem(nodeStruct<T> *node);
protected:
nodeStruct<T> *tail;
};
//--------------------------queueClass member functions----------------------//
template <class T>
queueClass<T>::queueClass(const queueClass<T>& Q)
{
num_items = Q.NumItems();
if (Q.head == NULL)
head = NULL;
else
{
// make sure we can allocate a new struct
assert((head = new nodeStruct<T>) != NULL);
// and a new data item
assert((head->data = new T) != NULL);
// now copy the data over
head->data = Q.head->data;
// zoom through the list creating the data properly and allocating memory
for (nodeStruct<T> *temp = Q.head->next, *newlist = head; temp;
temp = temp->next)
{
assert ((newlist->next = new nodeStruct<T>) != NULL);
newlist = newlist->next;
assert ((newlist->data = new T) != NULL);
newlist->data = temp->data;
}
// the last 'next' pointer must = NULL
newlist->next = NULL;
}
}
// all I have to do here is set tail to NULL, the actual items get deleted
// when the base class destructors get called
template <class T>
queueClass<T>::~queueClass()
{
tail = NULL;
}
// in a queue, you add items to the tail, and retrieve them from the head
// but since we are using listClass as a base class, when you add an item
// it goes into the head, so things work kinda backwards
template <class T>
bool queueClass<T>::EnQueue(T *item)
{
// what I do here is add an item and move the 'tail' pointer up one
// so I know where to pull items from
if (head)
{
assert (AddItem(NULL, item));
tail = tail->next;
}
else
{
assert (AddItem(NULL, item));
tail = head;
}
}
// the obvious problem with dequeue is having to move the tail up the list
// one -- one of the many cases for using doubly linked lists
// of course, this is also a great example of why OOP is cool, as I can go
// back in and change the base class which implements how the lists work
// and it won't affect how the program runs
template <class T>
bool queueClass<T>::DeQueue()
{
// first we remove the item
RemoveItem(tail);
// then we zoom through the list and find out where the tail should really
// be
register nodeStruct<T> *temp = head;
while (temp)
temp = temp->next;
tail = temp;
}