====== Queue in C++ ======
===== MyQueue =====
//Eine Queue ist intern eine doppelt verkettete Liste, jedes Element repräsentiert dabei eine Instanz der Klasse "MyNode"
template
class MyQueue
{
private:
MyNode* head; //Der Head unserer Queue, hier beginnt sie
MyNode* tail; //Der Tail unserer Queue, hier endet sie
public:
MyQueue();
~MyQueue();
void push(T value); //Mit der Push-Methode wird ein Element am Ende der Queue eingefügt (enqueue)
void pop(); //Mit der Pop-Methode wird ein Element am Anfang der Queue gelöscht (dequeue)
MyNode* getHead(); //Mit dieser Methode bekommt man den Head geliefert
MyNode* getTail(); //Mit dieser Methode bekommt man den Tail geliefert
bool isEmpty(); //Diese Methode checkt, ob unsere Queue leer ist und liefert dann einen Boolean Wert zurück
void deleteList(); //Diese Methode löscht unsere ganze Queue
template
friend ostream& operator << (ostream& os, const MyQueue& queue);
};
template
MyQueue::MyQueue() //Im Konstruktor werden nur der Head bzw. der Tail auf NULL gesetzt
{
this->head = this->tail = NULL;
}
template
MyQueue::~MyQueue()
{//Im Destruktor wird einfach der Speicher den die einzelnen Elemente der Queue beanspruchen mithilfe der Methode "deleteList()" freigegeben
this->deleteList();
}
template
void MyQueue::deleteList()
{//In dieser Methode wird die Liste vom ersten bis zum letzten Element durchlaufen, dabei wird immer das erste Element gelöscht
MyNode* help = this->head;
while(!this->isEmpty()) //Solange "help" nicht NULL ist, können haben wir ein Element welches wir löschen können
{
this->pop();
}
this->head = this->tail = NULL;
}//Zu guter Letzt setzten wir "head" und "tail" auf NULL um problemlos mit der Queue weiterarbeiten zu können
template
void MyQueue::push(T value) //Dem Push wird der Wert übergeben, den das neue Queue-Element haben soll
{
MyNode* help = new MyNode(value); //Mit dem übergebenen Wert wird ein neues Element angelegt
if(this->isEmpty()) //Hier wird überprüft, ob die Queue bereits ein Element beinhaltet
this->head = help; //Wäre dies nicht der Fall, so wird der Head unserer Queue auf das neue Element gesetzt
else
this->tail->setNext(help); //Beinhaltet unsere Queue mind. 1 Element so wird das neue Element hinten drangehängt
help->setPrev(this->tail); //Zum Schluss noch die Pointer des neuen (letzten) Elements auf das vorletzte Element zeigen lassen
this->tail = help;//Das neue Element ist nun das Letzte, deshalb unseren Tail (zeigt immer auf letztes Element) auf das neue Element zeigen lassen
}
template
void MyQueue::pop() //Das Pop enfernt das 1. Element der Queue
{
if(!this->isEmpty()) //Es wird überprüft ob sich ein Element in der Queue befindet
{
MyNode* help = this->head;//Falls wir ein Element haben, setzten wir unseren Hilfszeiger help auf dieses und unseren "head" auf das Nächste
this->head = this->head->getNext(); //Wenn kein Element mehr da ist, wird "head" AUTOMATISCH auf NULL gesetzt
if(this->head != NULL)
this->head->setPrev(NULL); //Der Zeiger zum vorderen Element wird gekappt
else
this->tail = NULL; //Wenn "head" NULL ist, wird "tail" auch auf NULL gesetzt
help->setNext(NULL); //Nur noch "help" zeigt auf das zu löschende Element"
delete help; //Der Speicher den das Element beansprucht wird freigegeben
}
}
template
MyNode* MyQueue::getHead()
{
return this->head; //Diese Methode liefert einfach den Beginn der Queue (head) zurück
}
template
MyNode* MyQueue::getTail()
{
return this->tail; //Diese Methode liefert einfach das Ende der Queue (tail) zurück
}
template
bool MyQueue::isEmpty() //Diese Methode checkt, ob die Queue leer ist
{ //Ist sie leer, wird "true" zurückgeliefert, enthält sie mindestens ein Element, wird "false" geliefert
bool ret = false;
if(this->head == NULL && this->tail == NULL)
ret = true;
return ret;
}
template
ostream& operator << (ostream& os, const MyQueue& queue)
{//Mit dem überladenen Output-Operator kann man unsere Queue ganz einfach ausgegeben werden
MyNode* help = queue.head;
while(help != NULL)
{//Wir durchlaufen einfach die Queue vom ersten bis zum letzten Element und geben dabei den Wert jedes einzelnen Elements aus
cout << help->getValue() << " ";
help = help->getNext();
}
return os;
}
===== MyNode =====
template
class MyNode //Eine Node ist ein Element der Queue
{
private:
MyNode* next; //Pointer der auf das folgende Element zeigt
MyNode* prev; //Pointer der auf das vorhergehende Element zeigt
T value;
public:
MyNode(T value);
void setValue(T value); //Methode um explizit den Wert eines Elements neu zu setzten
T getValue(); //Liefert den Wert des aktuellen Elements
MyNode* getNext(); //Liefert das nächste Element
MyNode* getPrev(); //Liefert das vorhergehende Element
void setNext(MyNode* node); //Biegt den Zeiger, der auf das nächste Element zeigt, auf das übergebene Element um
void setPrev(MyNode* node); //Biegt den Zeiger, der auf das vorhergehende Element zeigt, auf das übergebene Element um
};
template
MyNode::MyNode(T value) //Im Konstruktor wird dem Element ein Wert (value) zugewiesen,
//"next" und "prev" werden dabei auf NULL gesetzt
{
this->next = NULL;
this->prev = NULL;
this->value = value;
}
template
void MyNode::setValue(T value)
{
this->value = value; //Methode um den Wert des Elements neu zu setzen
}
template
T MyNode::getValue()
{
return this->value; //Liefert den Wert des Elements
}
template
MyNode* MyNode::getNext()
{
return this->next; //Liefert das Element auf das der "next"-Pointer verweist
}
template
MyNode* MyNode::getPrev()
{
return this->prev; //Liefert das Element auf das der "prev"-Pointer verweist
}
template
void MyNode::setNext(MyNode* node)
{
this->next = node; //Diese Methode setzt den "next"-Pointer auf ein neues Element
}
template
void MyNode::setPrev(MyNode* node)
{
this->prev = node; //Diese Methode setzt den "prev"-Pointer auf ein neues Element
}