Inhaltsverzeichnis

Queue in C++

MyQueue

//Eine Queue ist intern eine doppelt verkettete Liste, jedes Element repräsentiert dabei eine Instanz der Klasse "MyNode"
template <class T>
class MyQueue 
{
    private:
        MyNode<T>* head; //Der Head unserer Queue, hier beginnt sie
        MyNode<T>* 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<T>* getHead(); //Mit dieser Methode bekommt man den Head geliefert
        MyNode<T>* 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 <class T>
        friend ostream& operator << (ostream& os, const MyQueue<T>& queue); 
};
 
template <class T>
MyQueue<T>::MyQueue()   //Im Konstruktor werden nur der Head bzw. der Tail auf NULL gesetzt
{
    this->head = this->tail = NULL;
}
 
template <class T>
MyQueue<T>::~MyQueue() 
{//Im Destruktor wird einfach der Speicher den die einzelnen Elemente der Queue beanspruchen mithilfe der Methode "deleteList()" freigegeben
    this->deleteList();
}
 
template <class T>
void MyQueue<T>::deleteList() 
{//In dieser Methode wird die Liste vom ersten bis zum letzten Element durchlaufen, dabei wird immer das erste Element gelöscht
    MyNode<T>* 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 <class T>
void MyQueue<T>::push(T value) //Dem Push wird der Wert übergeben, den das neue Queue-Element haben soll
{
    MyNode<T>* help = new MyNode<T>(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 <class T>
void MyQueue<T>::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<T>* 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 <class T>
MyNode<T>* MyQueue<T>::getHead()
{
    return this->head; //Diese Methode liefert einfach den Beginn der Queue (head) zurück
}
 
template <class T>
MyNode<T>* MyQueue<T>::getTail()
{
    return this->tail; //Diese Methode liefert einfach das Ende der Queue (tail) zurück
}
 
template <class T>
bool MyQueue<T>::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 <class T>
ostream& operator << (ostream& os, const MyQueue<T>& queue) 
{//Mit dem überladenen Output-Operator kann man unsere Queue ganz einfach ausgegeben werden
    MyNode<T>* 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 T>
class MyNode //Eine Node ist ein Element der Queue
{
    private:
        MyNode<T>* next;  //Pointer der auf das folgende Element zeigt
        MyNode<T>* 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<T>* getNext(); //Liefert das nächste Element
        MyNode<T>* getPrev(); //Liefert das vorhergehende Element
 
        void setNext(MyNode<T>* node); //Biegt den Zeiger, der auf das nächste Element zeigt, auf das übergebene Element um
        void setPrev(MyNode<T>* node); //Biegt den Zeiger, der auf das vorhergehende Element zeigt, auf das übergebene Element um
};
 
template <class T>
MyNode<T>::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 <class T>
void MyNode<T>::setValue(T value)
{
    this->value = value; //Methode um den Wert des Elements neu zu setzen
}
 
template <class T>
T MyNode<T>::getValue()
{
    return this->value; //Liefert den Wert des Elements
}
 
template <class T>
MyNode<T>* MyNode<T>::getNext()
{
    return this->next; //Liefert das Element auf das der "next"-Pointer verweist
}
 
template <class T>
MyNode<T>* MyNode<T>::getPrev()
{
    return this->prev; //Liefert das Element auf das der "prev"-Pointer verweist
}
 
template <class T>
void MyNode<T>::setNext(MyNode<T>* node)
{
    this->next = node; //Diese Methode setzt den "next"-Pointer auf ein neues Element
}                      
 
template <class T>
void MyNode<T>::setPrev(MyNode<T>* node)
{
    this->prev = node; //Diese Methode setzt den "prev"-Pointer auf ein neues Element
}