Institut für Kartographie und Geoinformation Prof. Dr. Lutz Plümer Diskrete Mathematik I Vorlesung Listen-
2 letzte Stunde: rekursive Definitionen und Methoden heute: rekursive Datenstrukuren: Listen Rekursion
3 Übersicht Listen –... als rekursive Struktur –... als dynamische Datenstrukturen Die Klasse Element –... mit Element-konstruktor Eine richtige kleine Liste Ein UML-Diagramm für Element Aber wie kommt man nun zu einer Liste? Anfügen von Elementen - Beispiel
4 Übersicht (Fortsetzung) Einfügen am Anfang einer Liste –Problem –Beispiel –Problem der bisherigen Lösung Die Klasse Liste (UML-Diagramm) Die Klasse Element (vollständig) Die Klasse Liste
5 Listen als rekursive Struktur Die leere Liste Null ist eine Liste. Wenn E ein Element ist und L eine Liste, dann ist E L eine Liste. Beispiele: –die leere Liste { } –{1} –{1,3,2,5} Graphik für die leere Liste:
6 Listen als Dynamische Datenstrukturen flexible Datenstruktur ohne vorherige Festlegung auf die Größe Vorteile gegenüber Arrays – beliebige Größenänderungen – effiziente Umordnung der Elemente Nachteil gegenüber Arrays – kein direkter Zugriff auf einzelne Elemente
7 class Element { int wert; Element weiter; } 5 Elemen t int Zeiger auf ein Element Die Klasse Element
8 class Element { Element(int i) { wert = i; weiter = null;} int wert; Element weiter; }... mit Element-konstruktor Das ist neu Die Prozedur Element(int i) ist ein Konstruktor, der bei der Erzeugung eines Elements mit new Element(i) automatisch aufgerufen wird.
9 5 Die leere Liste 37 Der Kopf der Liste Der Rest der Liste Eine richtige kleine Liste
10 Ein UML-Diagramm für Element Element +Element(i : int) -wert : int weiter 0..1 Beachte: weiter ist kein Attribut, sondern eine Beziehung eine (UML-) Beziehung wird (in Java) als Attribut einer zugehörigen Klasse implementiert eine UML-Beziehung kann auch rekursiv sein Beziehung Konstruktor Ein oder kein Nachfolger 0..1
11 Aber wie kommt man nun zu einer Liste? Wir haben: –die Klasse Element Eine Liste entsteht durch Erzeugung und Verkettung von Objekten vom Typ Element – Erzeugen des ersten Elements mit dem Konstruktor Element – Anfügen eines Elemente zusätzliche Prozedur
12 void FügeAn(int neuerWert) { Element lauf = this; while (lauf.weiter != null) lauf = lauf.weiter; lauf.weiter = new Element(neuerWert); } Zeiger auf das aufrufende Objekt Sucht das letzte Element fügt neues Element an Anfügen von Elementen
Element kopf; class Element { Element(int i) { wert = i; weiter = null; } int wert; Element weiter; } kopf
Element kopf; kopf = new Element(25); class Element { Element(int i) { wert = i; weiter = null; } int wert; Element weiter; } kopf
Element kopf; kopf = new Element(25); class Element { Element(int i) { wert = i; weiter = null; } int wert; Element weiter; } kopf 25
Element kopf; kopf = new Element(25); kopf.FügeAn(22); void FügeAn(int neuerWert) { Element lauf = this; while (lauf.weiter != null) lauf = lauf.weiter; lauf.weiter = new Element(neuerWert); } 25 kopf
Element kopf; kopf = new Element(25); kopf.FügeAn(22); void FügeAn(int neuerWert) { Element lauf = this; while (lauf.weiter != null) lauf = lauf.weiter; lauf.weiter = new Element(neuerWert); } lauf 25 kopf
Element kopf; kopf = new Element(25); kopf.FügeAn(22); void FügeAn(int neuerWert) { Element lauf = this; while (lauf.weiter != null) lauf = lauf.weiter; lauf.weiter = new Element(neuerWert); } 25 kopf 22
Element kopf; kopf = new Element(25); kopf.FügeAn(22); void FügeAn(int neuerWert) { Element lauf = this; while (lauf.weiter != null) lauf = lauf.weiter; lauf.weiter = new Element(neuerWert); } 25 kopf 22
Element kopf; kopf = new Element(25); kopf.FügeAn(22); kopf.FügeAn(28); void FügeAn(int neuerWert) { Element lauf = this; while (lauf.weiter != null) lauf = lauf.weiter; lauf.weiter = new Element(neuerWert); } 2225 kopf
Element kopf; kopf = new Element(25); kopf.FügeAn(22); kopf.FügeAn(28); void FügeAn(int neuerWert) { Element lauf = this; while (lauf.weiter != null) lauf = lauf.weiter; lauf.weiter = new Element(neuerWert); } lauf 2225 kopf
Element kopf; kopf = new Element(25); kopf.FügeAn(22); kopf.FügeAn(28); void FügeAn(int neuerWert) { Element lauf = this; while (lauf.weiter != null) lauf = lauf.weiter; lauf.weiter = new Element(neuerWert); } 2225 kopf lauf
Element kopf; kopf = new Element(25); kopf.FügeAn(22); kopf.FügeAn(28); void FügeAn(int neuerWert) { Element lauf = this; while (lauf.weiter != null) lauf = lauf.weiter; lauf.weiter = new Element(neuerWert); } 2225 kopf lauf
Element kopf; kopf = new Element(25); kopf.FügeAn(22); kopf.FügeAn(28); void FügeAn(int neuerWert) { Element lauf = this; while (lauf.weiter != null) lauf = lauf.weiter; lauf.weiter = new Element(neuerWert); } kopf lauf
Element kopf; kopf = new Element(25); kopf.FügeAn(22); kopf.FügeAn(28); void FügeAn(int neuerWert) { Element lauf = this; while (lauf.weiter != null) lauf = lauf.weiter; lauf.weiter = new Element(neuerWert); } kopf
Element kopf; kopf = new Element(25); kopf.FügeAn(22); kopf.FügeAn(28); void FügeAn(int neuerWert) { Element lauf = this; while (lauf.weiter != null) lauf = lauf.weiter; lauf.weiter = new Element(neuerWert); } kopf
kopf Problem: Einfügen am Anfang einer Liste Problem: es gibt bislang nur die Klasse Element die Operation Einfügen muß vom ersten Element aufgerufen werden Umsetzung der Referenz kopf erforderlich das Kopf-Element hat aber keinen Zugriff auf die Referenz kopf Lösung: Umkopieren von Wert
28 void FügeEin(int neuerWert) { Element neuesElement = new Element(wert); neuesElement.weiter = weiter; weiter = neuesElement; wert = neuerWert; } Einfügen am Anfang einer Liste
kopf void FügeEin(int neuerWert) { Element neuesElement = newElement(wert); neuesElement.weiter = weiter; weiter = neuesElement; wert = neuerWert; } kopf.FügeEin(17) Einfügen am Anfang einer Liste
kopf void FügeEin(int neuerWert) { Element neuesElement = newElement(wert); neuesElement.weiter = weiter; weiter = neuesElement; wert = neuerWert; } 25 neuesElement Einfügen am Anfang einer Liste
kopf void FügeEin(int neuerWert) { Element neuesElement = newElement(wert); neuesElement.weiter = weiter; weiter = neuesElement; wert = neuerWert; } neuesElement Einfügen am Anfang einer Liste 25
kopf void FügeEin(int neuerWert) { Element neuesElement = newElement(wert); neuesElement.weiter = weiter; weiter = neuesElement; wert = neuerWert; } Einfügen am Anfang einer Liste 25
kopf void FügeEin(int neuerWert) { Element neuesElement = newElement(wert); neuesElement.weiter = weiter; weiter = neuesElement; wert = neuerWert; } Einfügen am Anfang einer Liste 25
kopf void FügeEin(int neuerWert) { Element neuesElement = newElement(wert); neuesElement.weiter = weiter; weiter = neuesElement; wert = neuerWert; } 25 Einfügen am Anfang einer Liste
kopf void FügeEin(int neuerWert) { Element neuesElement = newElement(wert); neuesElement.weiter = weiter; weiter = neuesElement; wert = neuerWert; } 25 Einfügen am Anfang einer Liste
kopf void FügeEin(int neuerWert) { Element neuesElement = newElement(wert); neuesElement.weiter = weiter; weiter = neuesElement; wert = neuerWert; } 25 Einfügen am Anfang einer Liste
37 Problem der bisherigen Lösung Einfügen am Anfang mehr als umständlich Einfügen am Ende ineffizient, insbesondere wenn die Liste sehr lang ist wo liegt das Problem? bisheriges Modell –wir haben zwar eine Klasse Element –aber keine Klasse Liste Lösung: Definition einer Klasse Liste –Verweis auf das erste Element –Verweis auf das letzte Element
38 Liste 0..1 kopf 0..1 fuß 0..1 Element +Element(i : int) -wert : int weiter 0..1 Die Klasse Liste
39 class Element { private int wert; private Element weiter; Element(int i) { wert = i; weiter = null; } Element(int i, Element e) { wert = i; weiter = e; } void SetzeWert(int i) { wert = i; } int GibWert() { return wert; } void SetzeWeiter(Element e) { weiter = e; } Element GibWeiter() { return weiter; } } beachte: der Konstruktor Element kann sowohl ein- als auch zweistellig aufgerufen weden (Überladung) neu Die Klasse Element (vollständig)
class Liste { Liste() { kopf = fuß = null; } Liste(int w) { kopf = fuß = new Element(w); } private Element kopf, fuß; void FügeAn(int an) { Element neu = new Element(an); if (fuß != null) { fuß.SetzeWeiter(neu); fuß = neu; } else kopf = fuß = neu; } void FügeEin(int ein) { kopf = new Element(ein, kopf); if (fuß == null) fuß = kopf; } beachte die Fallunterscheidung der leeren Liste! leere Liste Die Klasse Liste