Programmieren I Kapitel 13. Listen
Kapitel 13: Listen Ziel: eigene Datenstrukturen erstellen können und eine wichtige vordefinierte Datenstruktur( familie) kennenlernen zusammengehörige Elemente zusammenfassen Ergebnis in abstrakte Datentypen kapseln vordefinierte Varianten Iteratoren
Idee von Listen / Sequenzen Ziel: zusammengehörige Elemente hintereinander schreiben Frage: Unterschied zum Array?? kein direkter Zugriff auf Elemente in der Mitte nötig/möglich + Anzahl der Elemente unbekannt und dynamisch variabel Lösungsidee: jedes Element zusätzlich mit einer Referenz versehen, die auf das nächste Element verweist.
Idee von Listen / Sequenzen Definition: eine Liste besteht aus Zellen, von denen jede aus zwei Teilen besteht: das eigentliche Element selbst und eine Verkettung zum nächsten Listenelement. Das letzte Listenelement hat als Referenz null. Eine Liste besteht aus einer linearen Folge von Zellen.
Definition von Listen im alten Java class Cell { Object content; Cell next; Cell (Object content, Cell next) { this.content = content; this.next = next; Beachte: keinesfalls next als Feld von content machen (miserabler Stil!), sondern die Listendinge von den Inhaltsdingen trennen ( separation of concerns )
Aufbau von Listen im alten Java A B C Variante 1: Cell c3 = new Cell(C, null); Cell c2 = new Cell(B, c3); Cell c1 = new Cell(A, c2); Alternative (ohne rückwärts denken zu müssen): Cell c = new Cell(A, new Cell(B, new Cell(C,null)));
Standardoperationen auf Listen: vorne einfügen vorher h nachher h B C A B C vorne einfügen: h = new Cell(A, h);
Standardoperationen auf Listen: Einfügen hinter einem Element z vorher z B X A C nachher z X A B C Einfügen hinter dem Element z: z.next = new Cell(B, z.next); unnötiger Sonderfall: einfügen hinter dem letzten Element z: z.next = new Cell(B, null);
Standardoperationen auf Listen: Löschen des Nachfolgers von einem Element z vorher z X A B C nachher z X A C Löschen des Nachfolgers von dem Element z: z.next = z.next.next; B ist dadurch u.u. Speichermüll geworden
Standardoperationen auf Listen: Traversierung (Durchlauf) Zweck: suchen, allg: konsoldieren (fold, reduce): Länge, Summe, Mittelwert,... kopieren (teilweise) und filtern Funktionsanwendung auf alle Elemente (map)
Standardoperationen auf Listen: Traversierung (Durchlauf) Programmbeispiel suchen : Cell search(cell start, Object x) { Cell actual = start; while (actual!= null) { if (actual.content.equals(x)) { break; actual = actual.next; return actual;
Standardoperationen auf Listen: Traversierung (Durchlauf) Programmbeispiel Mittelwert : double average(cell start) { double sum = 0.0; int length = 0; Cell actual = start; while (actual!= null) { Measurement m = (Measurement)(actual.content); sum += m.value; length ++; actual = actual.next; if (length == 0) { return 0.0; else { return sum/length;
Definition von generischen Listen (sauberere Lösung) Definition der Klasse Cell mit generischen Typen: class Cell<Data> { Data content; Cell<Data> next; Cell (Data content, Cell<Data> next) { this.content = content; this.next = next;
Traversierung generischer Listen Programmbeispiel Mittelwert : double average(cell<measurement> start) { double sum = 0.0; int length = 0; Cell<Measurement> actual = start; while (actual!= null) { Measurement m = (Measurement)(actual.content); sum += m.value; length ++; actual = actual.next; if (length == 0) { return 0.0; else { return sum/length;
Aufbau zirkulärer Listen: Varianten von Listen: zirkuläre Listen A B C Cell<Point> last = new Cell<Point>(C,null); Cell<Point> triangle = new Cell<Point>(A, new Cell<Point>(B, last)); last.next = triangle; Typisch: Zyklus erst am Ende schließen
Traversierung zirkulärer Listen: Varianten von Listen: zirkuläre Listen Cell<Point> search(cell<point> start, Point p) { Cell<Point> result = null; Cell<Point> actual = start; do { if (actual.content.equals(p)) { result = actual; break; actual = actual.next; while (actual!= start); return result;
Varianten von Listen: doppelt verkettete Listen Struktur doppelt verketteter Listen: A B C class Dcell<Data> { Data content; Dcell<Data> prev, next; Dcell(Data x, Dcell<Data>p, Dcell<Data>n) { this.content = x; this.prev = p; this.next = n;
Listen??? A B C D E F G Wer Zugriff auf die next Referenzen hat, kann die Liste zerstören! Folge: Kapselung der Listenstruktur => abstrakte Datentypen
Abstrakte Datentypen Verhindere Zugriff von außen auf die Datenstruktur! Das erlaubt Kontrolle und damit Sicherheit, Korrektheit, Modularität. Dazu: kein Haufen von Zellen, sondern eine Struktur, die von außen nur durch Methoden und damit kontrolliert zugreifbar ist. Damit ist Implementierung losgelöst von der abstrakten Sicht. Beispiel: vordefinierte java.util.linkedlist und der Anfang der Implementierung einer solchen Klasse in MyLinkedList.java
Listenähnliche Datenstrukturen allgemeine Collection.html und die Listerweiterungen (lineare, also indizierbare Struktur) Bemerkung: Kombination von Interfaces und abstrakten Klassen
Listenähnliche Datenstrukturen Vergleich Set: wie Collection, aber semantisch ohne Mehrfacheinträge List: linear indiziert, Mehrfacheinträge möglich ArrayList: schnellerer Zugriff, langsamerer Update LinkedList: langsamerer Zugriff, schnellerer Update Vector: ArrayList, also dynamisches Array (synchronisiert, legacy) Stack: Hinzufügen und Entfernen nur an einem Ende Queue: Hinzufügen an einem, Entfernen am anderen Ende
Listenähnliche Datenstrukturen Typische Methodennamen für Stack und Queue push: Element hinzufügen pop: Element entfernen peek oder top: nächstes verfügbares (also zu löschendes) Element lesen, aber nicht entfernen empty: Test auf Leerheit
Iterator Zweck: durchlaufen der Datenstruktur analog zu Arrays Interface: boolean hasnext() Object next() void remove() remove als einzige sichere Löschmethode während der Iteration Implementierungsbeispiel: siehe SuperLinkedList.java
Iterator Anwendung Beispiel (altes Java): LinkedList polygon; for (Iterator i=polygon.iterator(); i.hasnext(); ) { Point p = (Point)(i.next());... p... Beispiel mit der neuen for Schleife aus Java 1.5 für Klassen, die das Interface Iterable<Data> implementieren (z.b. Collections und Arrays): LinkedList<Point> polygon; for (Point p:polygon) {... p...
Zusammenfassung Idee von Listen Realisierung der ersten eigenen Datenstruktur mit Hilfe von Referenzen Notwendigkeit zum Schutz => abstrakter Datentyp Listenähnliche Datenstrukturen Iteratoren