Anstatt beispielsweise einer Queue, bei der wir ein head
und ein tail
Element haben, über die wir auf den Anfang und das Ende der Queue zugreifen können, haben wir nun die List mit 3 möglichen “Eingriffspunkten”.
Wie bei der Queue haben wir auch ein Element am Anfang (first
) und am Ende (last
). Zusätlich zu diesen beiden gibt es noch das current
Element, dass über die List bewegt werden kann. Wir haben damit die Möglichkeit bekommen, dass wir auf alle Elemente in einer Datenstruktur zugreifen können, ohne eines der anderen Element entfernen zu müssen!
Methoden
Im folgenden werden die wichtigsten Methode aus der Klasse List erläutert.
hasAccess()
Die Methode liefert einen boolean
Wert zurück, der angibt, ob das aktuelle Element auf ein Element zugreift.
toFirst()
und toLast()
toFirst()
setzt das aktuelle Element auf das erste Element. Im Gegensatz dazu setzt toLast()
das aktuelle Element auf das letzte Element.
setContent()
und getContent()
In dem Fall, dass es ein aktuelles Element gibt, kann mit den Methoden setContent()
und getContent()
der Inhalt des aktuellen Elementes bearbeitet/abgerufen werden.
append()
Mit der append()
Methode lassen sich Elemente hinten an die Liste anhängen. Dabei ist zu unterscheiden, ob die Liste leer ist, oder schon Elemente behinhaltet. Ist sie leer, so muss sowohl first
als auch last
auf das neue Element zeigen. In allen anderen Fällen wird mit der setNext()
Methode aus der internen Klasse Node
bestimmt, dass der Nachfolger des letzten Elementes das neu einzufügende Element ist. Anschließend muss dann noch last
auf das letzte Element gesetzt werden.
insert()
Die Methode insert()
fügt ein neues Element vor dem aktuellen Element ein. Dabei muss beachtet werden, dass es ein aktuelles Element geben muss, damit die Methode funnktioniert. In dem Fall, dass die List leer ist und es damit kein aktuelles Element geben kann, wird das neue Element zwar eingefügt, current
zeigt aber weiterhin auf kein Element.
Bei dieser Methode wird deutlich, dass man immer überprüfen muss, dass man alle möglichen Sonderfälle berücksichtigt hat. Folgenden Fälle könne häufig auftreten:
- Die Liste ist leer.
- Das neue Element wird am Anfang eingefügt.
- Das neue Element wird am Ende eingefügt.
- Das neue Element wird an einer anderen Stelle eingefügt.
Bei der beschriebenen Methode sind vor allem die Fälle 1, 2 und natürlich 4 wichtig. Insbesondere der Fall 2 ist von Beudeutung, da das neue Element immer vor dem aktuellen Element eingefügt wird, und wir vor dem ersten Element in der List kein Element haben.
Um das vorherige Element erst einmal zu finden, verwenden wir eine getPrevious()
Methode
Die oben abgebildete Methode liefert immer das Element, dass vor dem current
Element steht zurück, es sei denn es gibt kann Element davor. Das kann beispielsweise dann passieren, wenn current
auf das erste Element zeigt. In diesem Fall würde null
zurückgegeben werden.
Mit der Methode getPrevious()
kann nun bestimmt werden zwischen welchen beiden Elementen das neue Element in der insert()
Methode eingefügt werden soll: Zwischen getPrevious()
und current.
concat()
Die Methode concat()
fügt zwei Listen zusammen. Dabei wird der Methode eine Liste übergeben, die dann an die aktuelle Liste (this
) angehängt wird. Dabei muss wieder zwischen zwei Fällen unterschieden werden. Zum einen kann die aktuelle Liste leer sein, dann werden first
und last
der aktuellen Liste mit dem first
und last
der übergebenen Liste überschrieben. Andernfalls zeigt das last
Element der aktuellen Liste auf das erste Element der übergebenen Liste last
wird mit dem last
der übergebenen List überschrieben.
Da die übergebene Liste, die angehängt werden soll, leer sein soll, werden noch alle Möglichkeiten auf Liste zuzugreifen auf null
gesetzt.
remove()
remove()
löscht das aktuelle Element und setzt current
auf das nächste Element. Dabei wird auch hier der Vorgang in Fälle zerlegt, da es je nach Fall vorkommen kann, dass vor dem aktuellen Element in der Liste kein weiteres Element gibt, beziehungsweise nach dem aktuellen Element kein Element mehr vorhanden ist.
Nachdem dann auch das aktuelle Element verschoben wurde, wird nocheinmal überprüft, ob die Liste leer ist, da in diese Fall last
noch auf ein Element zeigen würde, first
aber auf null
.
List Sort
Das Sortieren mit Listen gestaltet sich als besonders einfach, da die Implementierung der verschiedenen Verfahren sich als relativ unkompliziert darstellt.
Quicksort
In der Implementierung des Verfahrens wird das erste Element in der Liste als Pivot Element genommen. Anhand diesem Elementes wird dann jedes Element in eine der zwei gegebenen Listen einsortiert. Für diese Listen wird dann jeweils die Methode rekursiv aufgerufen. Anschließend werden die Listen mit der concat()
Methode wieder zusammengefügt.
Mergesort
Für Mergesort wird noch eine Methode getListSize()
benötigt, da man immer die Liste in der Mitte teilt um sie dann wieder sortiert zusammenzufügen. Mit current
ist es zudem immer einfach den Pointer beim mergen darzustellen.
SortedList
Eine Erweiterung des List
ist die SortedList
. Sie fügt jeden Wert automatisch sortiert in die List ein. Dafür wird folgenden Struktur verwendet:
Architektur des SortedList
Quelle: Moodle
Zur Realisierung wird ein Interface verwendet. Dieses definiert Methoden, die dann von der Klasse implementiert werden, die das Interface implementiert. In obigen Bid wäre es die Klasse Item
, die das Interface Sortable
implementiert.
Der ContentType
der SortedList
muss von dem Interface Sortable
erben, da wir damit auf die Methode compareTo()
zugreifen können, wenn wir als Datentyp den ContentType
angeben.
Interface Sortable
Klasse Item
Wie in den oben abgebildeten Quelltexten zu erkennen, werden die Methoden, die im Interface deklariert wurden, in der Klasse Item
implementiert.
Hauptsächlich ist dabei die Methode compareTo()
von belangen, da diese benutzt wird, um zwei Strings zu vergleichen. Deshalb wird nicht mehr ein Integer verglichen und dann einsortiert, sondern ein String. Dieses Vorgehen ermöglicht uns, dass wird jedes Mögliche Objekt vergleichen können, solange wir ihm eine Id geben können (z.b. Autokennzeichen, Ip-Adresse, etc.)
Außerdem erbt die Klasse SortedList
von der Klasse List
um auf die Methoden zugreifen zu könne. Dabei werden die Methoden, die Verändert werden müssen, um ein Element sortiert einzufügen, in der Klasse SortedList
überschrieben.
Implementierung
Insbesondere die insert()
Methode muss überschrieben werden. Da sie praktischerweise auch von den anderen Methoden in der SortedList
Klasse aufgerufen wird, ist sie eine der wichtigsten Methoden.