Warteschlangen

4.3. Warteschlangen#

Warteschlangen (engl. Queue) arbeiten nach dem FIFO-Prinzip (First In, First Out), d.h. wer zuerst kommt, wird zuerst bedient. Konkret bedeutet das, dass ein neues Element hinten an die Warteschlange angehängt werden (mit der Operation queue()) und Elemente vorne aus der Warteschlange entnommen werden (mit der Operation dequeue()).

../_images/kd_queue_fosa.svg

Abb. 4.2 Klassendiagramm für den Datentyp Warteschlange (Queue) (FoSa 5.3)#

Aufgabe: Nimm den folgenden Code als Vorlage und baue daraus die Klasse Warteschlange, entsprechend dem UML-Diagramm aus Abb. 4.2.

Hinweis

  • Du brauchst ein zusätzliches Attribut. Das Klassendiagramm zeigt dir, welches!

  • Ändere auch die Methodennamen und Kommentare.

# Nimm diese Klasse als Vorlage und baue sie in die Klasse Warteschlange um

class Stapel:

    class Knoten:
        def __init__(self, inhalt, naechster=None):
            self.inhalt = inhalt
            self.naechster = naechster

    def __init__(self):
        self.anfang: Stapel.Knoten|None = None
        self.hoehe = 0 

    def push(self, daten):
        """legt ein neues Element auf den Stapel"""
        neuer_knoten = Stapel.Knoten(daten, self.anfang) 
        self.anfang = neuer_knoten 
        self.hoehe += 1  

    def pop(self):
        """entfernt das oberste Element vom Stapel und gibt es zurück"""
        if self.anfang is None:
            raise IndexError("Pop-Operation auf leerem Stapel nicht möglich")
        inhalt = self.anfang.inhalt  
        self.anfang = self.anfang.naechster 
        self.hoehe -= 1 
        return inhalt

    def top(self):
        """gibt das oberste Element des Stapels zurück, ohne es zu entfernen"""
        if self.anfang is None:
            raise IndexError("Top-Operation auf leerem Stapel nicht möglich")
        return self.anfang.inhalt

    def ist_leer(self):
        """gibt True zurück, wenn der Stapel leer ist, sonst False"""
        return self.anfang is None 
    
    def anzahl_elemente(self):
        """gibt die Anzahl der Elemente auf dem Stapel zurück"""
        return self.hoehe 

# Test
print("Tests für Warteschlange")
q = Warteschlange()
print("Leere Warteschlange ist leer:", q.ist_leer())
print("Anna, Berta und Cora stellen sich nacheinander an")
q.enqueue("Anna")
q.enqueue("Berta")
q.enqueue("Cora")
print("Länge der Warteschlange:", q.anzahl_elemente())
erste = q.dequeue()
print("Die erste Kundin wird bedient:", erste)
print("Länge der Warteschlange:", q.anzahl_elemente())
print("Die zweite Kundin wird bedient:", q.dequeue())
print("Dora stellt sich an")
q.enqueue("Dora")
print("Länge der Warteschlange:", q.anzahl_elemente())
weitere = ["Ella", "Frieda", "Greta"]
print("Weitere Kundinnen stellen sich an:", weitere)
for kundin in weitere:
    q.enqueue(kundin)
print("Länge der Warteschlange:", q.anzahl_elemente())
print("Alle verbleibenden Kundinnen werden bedient:")
while not q.ist_leer():
    print(q.dequeue())
print("Länge der Warteschlange:", q.anzahl_elemente())
Tests für Warteschlange
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[1], line 46
     44 # Test
     45 print("Tests für Warteschlange")
---> 46 q = Warteschlange()
     47 print("Leere Warteschlange ist leer:", q.ist_leer())
     48 print("Anna, Berta und Cora stellen sich nacheinander an")

NameError: name 'Warteschlange' is not defined

Lösung:

Hide code cell content
class Warteschlange:

    class Knoten:
        def __init__(self, inhalt, naechster=None):
            self.inhalt = inhalt
            self.naechster = naechster

    def __init__(self):
        self.kopf: Warteschlange.Knoten|None = None
        self.ende: Warteschlange.Knoten|None = None
        self.hoehe = 0 

    def enqueue(self, daten):
        """fügt ein neues Element in die Warteschlange ein"""
        neuer_knoten = Warteschlange.Knoten(daten, None) 
        if self.kopf is None:
            self.kopf = neuer_knoten 
        else:
            self.ende.naechster = neuer_knoten
        self.ende = neuer_knoten
        self.hoehe += 1

    def dequeue(self):
        """entfernt das vorderste Element aus der Warteschlange und gibt es zurück"""
        if self.kopf is None:
            raise IndexError("Dequeue-Operation auf leerer Warteschlange nicht möglich")
        inhalt = self.kopf.inhalt
        self.kopf = self.kopf.naechster
        if self.kopf is None:
            self.ende = None
        self.hoehe -= 1
        return inhalt

    def ist_leer(self):
        """gibt True zurück, wenn die Warterschlange leer ist, sonst False"""
        return self.kopf is None 
    
    def anzahl_elemente(self):
        """gibt die Anzahl der Elemente in der Warteschlange zurück"""
        return self.hoehe 

# Test
print("Tests für Warteschlange")
q = Warteschlange()
print("Leere Warteschlange ist leer:", q.ist_leer())
print("Anna, Berta und Cora stellen sich nacheinander an")
q.enqueue("Anna")
q.enqueue("Berta")
q.enqueue("Cora")
print("Länge der Warteschlange:", q.anzahl_elemente())
erste = q.dequeue()
print("Die erste Kundin wird bedient:", erste)
print("Länge der Warteschlange:", q.anzahl_elemente())
print("Die zweite Kundin wird bedient:", q.dequeue())
print("Dora stellt sich an")
q.enqueue("Dora")
print("Länge der Warteschlange:", q.anzahl_elemente())
weitere = ["Ella", "Frieda", "Greta"]
print("Weitere Kundinnen stellen sich an:", weitere)
for kundin in weitere:
    q.enqueue(kundin)
print("Länge der Warteschlange:", q.anzahl_elemente())
print("Alle verbleibenden Kundinnen werden bedient:")
while not q.ist_leer():
    print(q.dequeue())
print("Länge der Warteschlange:", q.anzahl_elemente())
Tests für Warteschlange
Leere Warteschlange ist leer: True
Anna, Berta und Cora stellen sich nacheinander an
Länge der Warteschlange: 3
Die erste Kundin wird bedient: Anna
Länge der Warteschlange: 2
Die zweite Kundin wird bedient: Berta
Dora stellt sich an
Länge der Warteschlange: 2
Weitere Kundinnen stellen sich an: ['Ella', 'Frieda', 'Greta']
Länge der Warteschlange: 5
Alle verbleibenden Kundinnen werden bedient:
Cora
Dora
Ella
Frieda
Greta
Länge der Warteschlange: 0