c++ queue template
- by Dalton Conley
ALright, pardon my messy code please. Below is my queue class.
#include <iostream>
using namespace std;
#ifndef QUEUE
#define QUEUE
/*----------------------------------------------------------------------------
Student Class
# Methods #
Student() // default constructor
Student(string, int) // constructor
display() // out puts a student
# Data Members #
Name // string name
Id // int id
----------------------------------------------------------------------------*/
class Student {
public:
Student() { }
Student(string iname, int iid) {
name = iname;
id = iid;
}
void display(ostream &out) const {
out << "Student Name: " << name << "\tStudent Id: " << id
<< "\tAddress: " << this << endl;
}
private:
string name;
int id;
};
// define a typedef of a pointer to a student.
typedef Student * StudentPointer;
template <typename T>
class Queue
{
public:
/*------------------------------------------------------------------------
Queue Default Constructor
Preconditions: none
Postconditions: assigns default values for front and back to 0
description: constructs a default empty Queue.
------------------------------------------------------------------------*/
Queue() : myFront(0), myBack(0) {}
/*------------------------------------------------------------------------
Copy Constructor
Preconditions: requres a reference to a value for which you are copying
Postconditions: assigns a copy to the parent Queue.
description: Copys a queue and assigns it to the parent Queue.
------------------------------------------------------------------------*/
Queue(const T & q) {
myFront = myBack = 0;
if(!q.empty()) {
// copy the first node
myFront = myBack = new Node(q.front());
NodePointer qPtr = q.myFront->next;
while(qPtr != NULL) {
myBack->next = new Node(qPtr->data);
myBack = myBack->next;
qPtr = qPtr->next;
}
}
}
/*------------------------------------------------------------------------
Destructor
Preconditions: none
Postconditions: deallocates the dynamic memory for the Queue
description: deletes the memory stored for a Queue.
------------------------------------------------------------------------*/
~Queue() {
NodePointer prev = myFront, ptr;
while(prev != NULL) {
ptr = prev->next;
delete prev;
prev = ptr;
}
}
/*------------------------------------------------------------------------
Empty()
Preconditions: none
Postconditions: returns a boolean value.
description: returns true/false based on if the queue is empty or full.
------------------------------------------------------------------------*/
bool empty() const {
return (myFront == NULL);
}
/*------------------------------------------------------------------------
Enqueue
Preconditions: requires a constant reference
Postconditions: allocates memory and appends a value at the end of a queue
description:
------------------------------------------------------------------------*/
void enqueue(const T & value) {
NodePointer newNodePtr = new Node(value);
if(empty()) {
myFront = myBack = newNodePtr;
newNodePtr->next = NULL;
} else {
myBack->next = newNodePtr;
myBack = newNodePtr;
newNodePtr->next = NULL;
}
}
/*------------------------------------------------------------------------
Display
Preconditions: requires a reference of type ostream
Postconditions: returns the ostream value (for chaining)
description: outputs the contents of a queue.
------------------------------------------------------------------------*/
void display(ostream & out) const {
NodePointer ptr;
ptr = myFront;
while(ptr != NULL) {
out << ptr->data << " ";
ptr = ptr->next;
}
out << endl;
}
/*------------------------------------------------------------------------
Front
Preconditions: none
Postconditions: returns a value of type T
description: returns the first value in the parent Queue.
------------------------------------------------------------------------*/
T front() const {
if ( !empty() )
return (myFront->data);
else
{
cerr << "*** Queue is empty -- returning garbage value ***\n";
T * temp = new(T);
T garbage = * temp;
delete temp;
return garbage;
}
}
/*------------------------------------------------------------------------
Dequeue
Preconditions: none
Postconditions: removes the first value in a queue
------------------------------------------------------------------------*/
void dequeue() {
if ( !empty() ) {
NodePointer ptr = myFront;
myFront = myFront->next;
delete ptr;
if(myFront == NULL)
myBack = NULL;
} else {
cerr << "*** Queue is empty -- "
"can't remove a value ***\n";
exit(1);
}
}
/*------------------------------------------------------------------------
pverloaded = operator
Preconditions: requires a constant reference
Postconditions: returns a const type T
description: this allows assigning of queues to queues
------------------------------------------------------------------------*/
Queue<T> & operator=(const T &q) {
// make sure we arent reassigning ourself
// e.g. thisQueue = thisQueue.
if(this != &q) {
this->~Queue();
if(q.empty()) {
myFront = myBack = NULL;
} else {
myFront = myBack = new Node(q.front());
NodePointer qPtr = q.myFront->next;
while(qPtr != NULL) {
myBack->next = new Node(qPtr->data);
myBack = myBack->next;
qPtr = qPtr->next;
}
}
}
return *this;
}
private:
class Node {
public:
T data;
Node * next;
Node(T value, Node * first = 0) : data(value),
next(first) {}
};
typedef Node * NodePointer;
NodePointer myFront,
myBack,
queueSize;
};
/*------------------------------------------------------------------------
join
Preconditions: requires 2 queue values
Postconditions: appends queue2 to the end of queue1
description: this function joins 2 queues into 1.
------------------------------------------------------------------------*/
template <typename T>
Queue<T> join(Queue<T> q1, Queue<T> q2) {
Queue<T> q1Copy(q1), q2Copy(q2);
Queue<T> jQueue;
while(!q1Copy.empty()) {
jQueue.enqueue(q1Copy.front());
q1Copy.dequeue();
}
while(!q2Copy.empty()) {
jQueue.enqueue(q2Copy.front());
q2Copy.dequeue();
}
cout << jQueue << endl;
return jQueue;
}
/*----------------------------------------------------------------------------
Overloaded << operator
Preconditions: requires a constant reference and a Queue of type T
Postconditions: returns the ostream (for chaining)
description: this function is overloaded for outputing a queue with <<
----------------------------------------------------------------------------*/
template <typename T>
ostream & operator<<(ostream &out, Queue<T> &s) {
s.display(out);
return out;
}
/*----------------------------------------------------------------------------
Overloaded << operator
Preconditions: requires a constant reference and a reference of type Student
Postconditions: none
description: this function is overloaded for outputing an object of type
Student.
----------------------------------------------------------------------------*/
ostream & operator<<(ostream &out, Student &s) {
s.display(out);
}
/*----------------------------------------------------------------------------
Overloaded << operator
Preconditions: requires a constant reference and a reference of a pointer to
a Student object.
Postconditions: none
description: this function is overloaded for outputing pointers to Students
----------------------------------------------------------------------------*/
ostream & operator<<(ostream &out, StudentPointer &s) {
s->display(out);
}
#endif
Now I'm having some issues with it. For one, when I add 0 to a queue and then I output the queue like so..
Queue<double> qdub;
qdub.enqueue(0);
cout << qdub << endl;
That works, it will output 0. But for example, if I modify that queue in any way.. like.. assign it to a different queue..
Queue<double> qdub1;
Queue<double> qdub2;
qdub1.enqueue(0;
qdub2 = qdub1;
cout << qdub2 << endl;
It will give me weird values for 0 like.. 7.86914e-316.
Help on this would be much appreciated!