Aufgabe 10.6


mitnichten, header is halt dann der endpunkt wenn man se einmal durchlaufen hat. und start is immer der header.vorgaenger, der user weiß ja nicht dass es dieses element gibt.


Und wo genau bringt dir das was? Ob du über die Liste iterierst bis du bei null bist oder bis du wieder am Anfang bist macht ja mal überhaupt keinen Unterschied.


beim einfügen und dequeuen ists angenehm, keine sonderfälle beachten zu müssen, ist halt wie n ring wo du zeug nei und rauspackst, zeiger bleiben dann immer dieselben


Aber du musst doch beim Einfügen eines Objekts mit einer Priorität, die kleiner als alle anderen in der akuellen Liste ist, schauen, ob du am Ende der Liste angekommen bist, sonst drehst du dich im Kreis. Und ob du dann überprüfst, aktuellesElement.nachfolger==kopf oder aktuellesElement.nachfolger==null ist der gleiche Aufwand.
Wie schaut deine Liste aus, wenn sie leer ist? Ist dann kopf.nachfolger==kopf.vorgaenger==kopf?


Ich hab mir ein paar Funktionen geschrieben, die auf den Elementen der Liste operieren und alle Operationen mit den Zeigern machen. Damit sind bei mir auch die Referenzen immer konsistent.
[m]chain(element1, element2),
unchain(element1, element2),
insertBefore(element, neu),
insertAfter(element, neu)[/m]

Und die behandeln auch die Fälle mit [m]null[/m] als Parameter (erstes oder letztes Element der Liste).

Es gibt bei enqueue() nur einen Sonderfall, wenn nämlich das einzufügende Element eine höhere Priorität hat als der Kopf. Wo soll es bei dequeue() Sonderfälle geben?

Das ist wohl eher der Fall, wenn es genau ein Element gibt. Bei leerer Liste müsste wohl [m]kopf == null[/m] sein.


Bei diesem Sonderfall macht es aber keinen Unterschied, ob man eine zyklische Liste hat oder nicht. Der einzige interessante Fall ist der am Ende der Liste.

So hatte ichs auch erst. Dann kriegt mans aber nicht mehr hin, mit dem Iterator das letzte verbleibende Element zu löschen, ohne dass man (meineserachtens unelegant) von der Iterator-Klasse auf den Listenkopf in der Überklasse zugreift. Jetzt ists bei mir so, dass head niemals ==null ist, sondern ein immer bestehendes Dummy-Element. head.nachfolger ist das erste richtige Element.


Warum sollte man das nicht hinbekommen? Gibt doch clear() :slight_smile:


Ja klar, ich finde es nur irgendwie unelegant auf die Oberklasse zuzugreifen, egal ob Listenkopf oder clear().


ja eben so ein dummy element wies auch in der vorlesung dran war, ich sortier halt beim einfügen gleich nach priorität, “ring” wird halt praktisch gedreht bis ma an die stelle kommt oder der nächste nachfolger der header wäre und dann einfach rein damit. ich fands angenehm. Und der Iterator macht auch keinerlei Zicken, also demnach :slight_smile: man kann uns dann kein plagiarismus vorwerfen :wink:


bin eiegntlichs chon länger fertig, aber komme gerade ins grübeln:

ich habs so, meine enqueue() ordnet sortiert ein.

in meinem enqueueAll() benutze ich einfach den iterator, der einfach ancheinander die werte ausgibt (die ja bei mirs ortiert sind, in der schlange, wegen enqueue() ) weil ich voraussetz die schlange is sortiert, und diese dann bis hasNext() false zurückgibt die werte der zweiten schlange mit enqueue() hinzufügt.

meine frage ist nun, darf ich das so machen, darf ich annehmen dass die zweite schlange die ich übergebe in enqueueAll() sortiert ist, also erstellt wurde mit meinem enqueue() oder kann es passieren dass die aus einer globalen datei da eingelesen wird und verwendet wird? gut mir fällt rgad auf, kann mir eiegntlich egal sein, denn is ja woscht ob die übergebene sortiert ist oder nicht, würde micha ebr trotzdem mal interessieren.


Die zweite muss nicht dein enqueue benutzt haben, aber sortiert muss sie sein, sonst wäre sie keine korrekte Warteschlange. Im Interface steht ja über iterator():


ich glaube nicht, dass die testen wenn man iterator auf diese 2te übergebene schlange anwendet, dass die auch sortiert kommen soll, das is nirgends spezifiziert, daher denk ich (ich habs genauso gemacht), wenn man den iterator intern anwendet auf diese 2te schlange und dann bei enqueueAll() eh mit seinem eigenen enqueue() arbeitet es egal is ob diese 2te schlange sortiert is oder nicht, da das eigene enqueue() ja sortiert. Dieses Iterator dingens in enqueueAll() macht man doch eh nur, weil man sich das casten sparen möchte beim einfügen und dass diese 2te übergebene schlange nicht kaputt geht.
Oder meint ihr die übergeben willkürliche Listen und gucken ob die Iterator Methode das richtige tut? Das denke ich nicht, um eine Schlange zu erzeugen müssen sie ja meine Implementierung anwenden und wenn dann iterator angewendet wird kommts ja richtig sortiert, alles andere wäre a weng sinnlos. Wie gesagt ich denke es ist egal ob in enqueueAll die übergebene Schlange sortiert ist oder nicht wenn man sein eigenes enqueue verwendet zum sortieren.


Ich habe das ganze mal ohne den Iterator gelöst; Man mache eine while schleife, rufe enq. auf mit maxPrio und front; danach folgt ein deq. Aufruf, und dann beginnt das ganze auch schon wieder von vorn, bis zB maxPrio Integer.MIN_VALUE zurückgibt.

Sollte genauso gut klappen.

Hauptmotivation dieser Lösung war, dass ich keine Ahnung habe, wie ich dort aus enqall heraus überhaupt auf den Iterator zugreife … g

enq. sortiert bei mir ebenfalls; lediglich das Alter muss man einfach der übergebenen Reihenfolge entnehmen. Wird schon hinhauen :wink:


Und dann ist die übergebene Schlange ja leer nach deiner Taktik… Nicht gerade das, was beabsichtigt wurde.


Hmm, das ist allerdings richtig. Das hatte ich während eines Testcases ebenfalls schonmal bemerkt.

Wie Schaffe ich den Zugriff auf den Iterator aus enqall heraus ? Muss ich eine neue Instanz vom Iterator machen ?

Ala Iterator bla = new Iterator ?

Aber wie schaffe ich da dann die Verbindung auf die Instanz schlange ? Vielleicht mit schlange.Iterator ?

edit: Ahh jetzt hat es dann doch noch geklappt; werde es dann mal umbauen. Danke Raim.


Besser ist es, die Elemente mit dem Iterator auszulesen und dann in dieser Reihenfolge an enqueue() zu übergeben. Die Reihenfolge muss dabei die gleiche sein, weil ja FIFO gilt.

Edit: Für den Zugriff auf den Iterator gibt es ja extra Warteschlange.iterator()


sagt mal hab ich den Kommentar überlesen, oder wie verwendet ihr das nachfolger/vorgaenger aus der Klasse Element? schluckt ihr den Cast mittlerweile einfach oder habt ihr eure Doppelverkettung drumherum gebaut? (ich bau sie jetzt einfach mal drumherum und weigere mich ein "kaputtes"™ Konzept zu verwenden! ;-))


Ich hab div. “private Element” Objekte, und benutze darüber dann auch nachfolger/vorgaenger. Dh. meine Verkettung wird mit den beiden realisiert :wink:


Intern darf ja komplett mit Element gearbeitet werden. Da Element von PriorisiertesElement erbt, kann das auch bei dequeue() und dem Iterator ohne Probleme zurückgegeben werden. Ich hab dieses Mal an keiner Stelle explizit casten müssen.

Steht ja auch so in der Aufgabe: “[…] mithilfe einer doppelt verketteten Liste
aus Element-Objekten […]”


also ich muss auch kein einziges mal casten