Schwerpunkte • Vergleich: Arrays – verkettete Listen • Listenarten • Implementation: 7. Verkettete Strukturen: Listen - Pascal (C, C++): über Datenstrukturen Æ Records (Structs) + Pointertyp - Java: über Klassen + Objektreferenzen Java-Beispiele: • Gängige Funktionen für Listen: IntList.java List.java Stack1.java length, nthElement, addToEnd, ... • Noch einmal 'Stack': diesmal unbeschränkt • Lokale Klassen K. Bothe, Institut für Informatik, HU Berlin, GdP, WS 2015/16 Version: 4. Jan. 2016 K. Bothe, Institut für Informatik, HU Berlin, GdP, WS 2015/16 2 Verkettete Listen Verkettete Liste: Folge von Elementen, die miteinander über Verweise (Zeiger) verkettet sind Verkettete Listen: Überblick und Grundprinzip Anfang der Liste: Beispiel: einfach verkettete Liste 2 Element (Zelle): 11 11 1 57 Inhalt Verweis auf (Nachfolger-) Element K. Bothe, Institut für Informatik, HU Berlin, GdP, WS 2015/16 3 K. Bothe, Institut für Informatik, HU Berlin, GdP, WS 2015/16 4 Verkettete Listen: Aufgabe Verkettete Listen: Vorzüge Grundaufgabe vieler Programme: Verkettete Liste: sehr flexible Datenstruktur Information abspeichern und wiederfinden • Beliebige Anzahl von Elementen (keine Größenbeschränkung) • Einfügen, Streichen von Elementen effizient Darstellung: Array, Liste, Baum ... Arrays: Anzahl der Elemente n muss erst zur Laufzeit festgelegt werden. int[] a = new int[n]; Array: Aber: einmal festgelegte Größe n kann nicht mehr verändert werden. Probleme mit Arrays: ... Æ n zu groß: Platz verschwendet Æ n zu klein: u. U. Laufzeitprobleme (Überlauf) Beispiele: - Compiler: Anzahl der Bezeichner eines Programms? einfügen streichen Viele Bewegungen von Elementen - Unterschiedliche Wörter in Goethe, 'Faust I'? (Aufgabe: Wie häufig kommen einzelne Wörter vor?) K. Bothe, Institut für Informatik, HU Berlin, GdP, WS 2015/16 5 Verkettete Liste: Operationen Beispiel: einfach verkettete Liste K. Bothe, Institut für Informatik, HU Berlin, GdP, WS 2015/16 6 Liste: weitere Operationen • Einfügen eines neuen Elements an beliebiger Stelle 2 11 1 57 2 11 1 57 99 (kein Verschieben von Daten) Neues Element anhängen: - Speicherplatz für neue Zelle anfordern (dynamisch zur Laufzeit) - Verweis auf diese Zelle einrichten Æ keine Längenbeschränkung 2 11 1 57 • Streichen eines beliebigen Elements 2 11 1 57 13 - Nur logisch gestrichen - Physisch noch im Speicher: Garbage Collector (Java System) gibt Speicher zurück K. Bothe, Institut für Informatik, HU Berlin, GdP, WS 2015/16 7 K. Bothe, Institut für Informatik, HU Berlin, GdP, WS 2015/16 8 Garbage Collector (Müllsammler) Listenarten • einfach verkettete Liste 2 Automatische Freigabe von nicht mehr benötigtem Speicherplatz *) durch das Java-Laufzeitsystem *) 11 1 57 1 57 Wovon hängt die konkrete Auswahl ab ? • zyklisch verkettete Liste Speicherplätze, die nicht über Variablen des Programms (direkt oder über Verweislisten) erreichbar sind 2 Æ Java: Programmierer muss sich in Java nicht um Freigabe kümmern (Teil der JVM realisiert das: Garbage Collector) 11 • doppelt verkettete Liste 2 11 1 57 - anders als in C++, Pascal, Modula-2 (dort: explizite Anweisungen zur Freigabe von Speicherplatz im Programm) • zyklisch doppelt verkettete Liste: analog - Technik stammt von funktionalen Sprachen: Lisp K. Bothe, Institut für Informatik, HU Berlin, GdP, WS 2015/16 9 K. Bothe, Institut für Informatik, HU Berlin, GdP, WS 2015/16 10 Implementation (von nun an: nur einfach verkettete lineare Liste) • Pascal (C, C++): mit Datenstrukturen Record (Struct) + Pointertyp Implementation verketteter Listen TYPE INTLIST = @ ZELLE; ZELLE = RECORD VALUE: INTEGER; REST: INTLIST END; IntList.java List.java VAR ANFANG: INTLIST; VALUE Zelle ANFANG: • Java: mit Klassen ... REST Java hat weder Records noch Pointer K. Bothe, Institut für Informatik, HU Berlin, GdP, WS 2015/16 11 K. Bothe, Institut für Informatik, HU Berlin, GdP, WS 2015/16 12 Implementation in Java class IntList Erzeugung einer Liste Rekursive Definition: Typ der Variablen = definierte Klasse { class IntList { private int value ; private IntList rest ; public IntList (int v, IntList next) { value = v; null Objekt: rest = next; leerer Verweis } ... private int value ; private IntList rest ; Wie Pascal-Record (eine Zelle) public IntList (int v, IntList next) { value = v; rest = next; } public int getValue () { return value; } in: List.java: 1 IntList list = new IntList(57, null); 2 list = new IntList(1, list); public void setValue (int val) { value = val; } 1 2 list public IntList getRest () { return rest; } ... 57 value null rest list } 13 value null rest 1 Mit Konstruktor: Listenerweiterung immer vorn K. Bothe, Institut für Informatik, HU Berlin, GdP, WS 2015/16 57 K. Bothe, Institut für Informatik, HU Berlin, GdP, WS 2015/16 14 Listenfunktionen: Überblick Erzeugung und Ausgabe einer Liste class List { public static void main (String[] args) { IntList list = new IntList(57, null); list = new IntList(1, list); list = new IntList(11, list); list = new IntList(2, list); list.find(57) list: 2 11 1 57 13 IntList temp; for (temp = list;temp != null; temp = temp.getRest()) System.out.println(temp.getValue() + ", "); System.out.println(); list.addToEndM(13) list.removeM(11) System.out.println(list.toString()); } } list.nth(2) % java List list 2 11 1 57 list.length() 2, 11, 1, 57, 4 list.addInorderM(12) 2, 11, 1, 57 K. Bothe, Institut für Informatik, HU Berlin, GdP, WS 2015/16 list.toString() 2, 11, 1, 57, 13 nur für sortierte Listen “M” im Methodennamen: Liste wird modifiziert 15 K. Bothe, Institut für Informatik, HU Berlin, GdP, WS 2015/16 16 Implementation von Listenfunktionen Wichtige Funktionen für Listen (1) class IntList { private int value ; private IntList rest ; public IntList (int v, IntList next)… Listen als Datenstrukturen betrachtet als … • Rekursive Datenstruktur (Liste = Listenkopf gefolgt von Restliste) Æ rekursiver Algorithmus natürlich VL public int length () … } • Länge der Liste • Iterative Datenstruktur (Liste = Folge von Elementen) Æ iterativer Algorithmus natürlich public int length () { if (rest == null) return 1; else return 1 + rest.length(); } Aufgabe: iterative Implementation selbst K. Bothe, Institut für Informatik, HU Berlin, GdP, WS 2015/16 17 Wichtige Funktionen für Listen (2) 18 Wichtige Funktionen für Listen (3) • Finde (Verweis auf) Zelle mit Inhalt 'key' • Finde Verweis auf die n-te Zelle public IntList find (int key) { if (value == key) Aktuelles Objekt: return this; Verweis auf aktuelle Zelle else if (rest == null) return null; Nicht gefunden else return rest.find(key); Suche weiter } Binäre Suche nicht möglich Æ O(n) = ½ n K. Bothe, Institut für Informatik, HU Berlin, GdP, WS 2015/16 public IntList nth (int n) if (n == 0) return this; else if (rest == null) return null; else return rest.nth(n-1); } { Schwachstellen von Listen: * Speicherbedarf * Suchzeiten K. Bothe, Institut für Informatik, HU Berlin, GdP, WS 2015/16 19 K. Bothe, Institut für Informatik, HU Berlin, GdP, WS 2015/16 20 Wichtige Funktionen für Listen (4) Wichtige Funktionen für Listen (5) • Füge Element entsprechend der Größe in eine (aufsteigend) sortierte Liste ein • Neue Zelle an das Ende der Æ Aufbau sortierter Listen: nur mit addInOrderM() Liste anhängen n kleinste Zahl: public IntList addInorderM (int n) { vorn einfügen if (n < value) return new IntList (n, this); else if (n == value) n bereits vorhanden: nicht einfügen return this; else if (rest == null) { n größte Zahl: rest = new IntList (n, null); hinten anfügen return this; sonst: } rekursiv in der Mitte einfügen else { rest = rest.addInorderM(n); return this; } } public void addToEndM (int val) { if (rest != null) // a cell in the middle rest.addToEndM(val); else // the last cell rest = new IntList(val, null); } Verkettung der Liste am Ende mit neuer Zelle K. Bothe, Institut für Informatik, HU Berlin, GdP, WS 2015/16 21 K. Bothe, Institut für Informatik, HU Berlin, GdP, WS 2015/16 22 Nacharbeiten der Listen-Implementation • Durcharbeiten: Stack beliebiger Größe s.addInorderM (20); • IntList.java • List.java value s: 1 2 6 • Verstehen: • Bilder malen Stack1.java rest (3. Fall: neue größte Zahl) • Aufgabe: Lokale Klassen • Iterative Lösung selbst implementieren K. Bothe, Institut für Informatik, HU Berlin, GdP, WS 2015/16 23 K. Bothe, Institut für Informatik, HU Berlin, GdP, WS 2015/16 24 Noch einmal 'Stack': diesmal unbeschränkt class Stack1 Klasse 'Stack': Daten durch Variable 'top' repräsentiert class Stack { { lokale Klasse Lokale Klasse private class Zelle Object inhalt; Zelle next; } (Datensammlung) { private class Zelle Object inhalt; Zelle next; } // Inhalt // Verweis // Inhalt // Verweis // Verweis auf oberste Zelle private Zelle top; // Verweis auf oberste Zelle private Zelle top; public Stack1() { top = null; } public boolean isempty() return top == null; } ... { Daten des Stack, Beginn der Liste ... } { top: } K. Bothe, Institut für Informatik, HU Berlin, GdP, WS 2015/16 25 'push': Liste vorn verlängern K. Bothe, Institut für Informatik, HU Berlin, GdP, WS 2015/16 26 Klasse 'Queue' (Warteschlange): Prinzip: vorn lesen, hinten anhängen: FIFO public void push (Object x) { Zelle neueZelle = new Zelle(); neueZelle.inhalt = x; neueZelle.next = top; top = neueZelle; } class Queue { Idee? private class Zelle { Object inhalt; //Inhalt Zelle next; //Verweis } vorher: // 2 Verweise: erste / letzte Zelle ... private Zelle first, last; top: last: nachher: neue Zelle: x ... first: Wo einfügen? Wo streichen? top: K. Bothe, Institut für Informatik, HU Berlin, GdP, WS 2015/16 FIFO: First in, First out (Queue) LIFO: Last in, First out (Stack) 27 K. Bothe, Institut für Informatik, HU Berlin, GdP, WS 2015/16 28 Bewertung: Verkettung in Java • Verkettete Strukturen: - Angelegenheit der Datenstrukturierung • Pascal, C, C++ u.v.a.: mit Datenstrukturen - Record-Typ + Pointer Typ • Java - Vermischung von Objektorientierung und Datenstrukturierung: - Objekterzeugung zur Pointergenerierung genutzt Missbrauch? - Klasse: Realisierung ADT - Grund: kein anderer Weg, da Portabilität oberstes Ziel von Java (Pointer: problematisch für Portabilität - Adressverwaltung) K. Bothe, Institut für Informatik, HU Berlin, GdP, WS 2015/16 29