Diskrete Mathe Diskrete Mathematik I Listen Vorlesung 4
Diskrete Mathe letzte Stunde: rekursive Definitionen und Methoden heute: rekursive Datenstrukuren: Listen Rekursion 1
Diskrete Mathe 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 Übersicht I
Diskrete Mathe 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“ Übersicht II
Diskrete Mathe 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: Listen als rekursive Struktur
Diskrete Mathe 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 Listen als Dynamische Datenstrukturen
Diskrete Mathe class Element { int wert; Element weiter; } Die Klasse Element 5 Elemen t Zeiger auf ein Element int A 4x
Diskrete Mathe mit Element-konstruktor Das ist neu Die Methode Element(int i) ist ein Konstruktor, der bei der Erzeugung eines Elements mit new Element(i) automatisch aufgerufen wird. class Element { Element(int i) { wert = i; weiter = null;} int wert; Element weiter; }
Diskrete Mathe A 7x Eine richtige kleine Liste 5 Die leere Liste 37 Der Kopf der Liste Der Rest der Liste
Diskrete Mathe 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 9 A 13x Ein UML-Diagramm für „Element“ weiter 0..1 Beziehung Konstruktor Ein oder kein Nachfolger 0..1 Element +Element(i : int) -wert : int
Diskrete Mathe 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 Elements zusätzliche Prozedur Aber wie kommt man nun zu einer Liste?
Diskrete Mathe void FügeAn(int neuerWert) { Element lauf = this; while (lauf.weiter != null) lauf = lauf.weiter; lauf.weiter = new Element(neuerWert); } Anfügen von Elementen Sucht das letzte Element Zeiger auf das aufrufende Objekt fügt neues Element an A 10x
Diskrete Mathe Kopf Element kopf; class Element { Element(int i) { wert = i; weiter = null; } int wert; Element weiter; } A 25x
Diskrete Mathe Element kopf; kopf = new Element(25); class Element { Element(int i) { wert = i; weiter = null; } int wert; Element weiter; } Kopf 12 A 25x
Diskrete Mathe Element kopf; kopf = new Element(25); class Element { Element(int i) { wert = i; weiter = null; } int wert; Element weiter; } 25 Kopf 12 A 25x
Diskrete Mathe 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 12 A 25x
Diskrete Mathe 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 12 A 25x
Diskrete Mathe 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); } Kopf A 25x
Diskrete Mathe 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); } Kopf A 25x
Diskrete Mathe 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); 12 A 25x
Diskrete Mathe 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 12 A 25x
Diskrete Mathe 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 25 lauf A 25x
Diskrete Mathe 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 25 lauf A 25x
Diskrete Mathe 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 12 A 25x
Diskrete Mathe 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 A 25x
Diskrete Mathe 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 A 25x
Diskrete Mathe 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 13 A 8x Problem: Einfügen am Anfang einer Liste kopf
Diskrete Mathe void FügeEin(int neuerWert) { Element neuesElement = new Element(wert); neuesElement.weiter = weiter; weiter = neuesElement; wert = neuerWert; } Einfügen am Anfang einer Liste
Diskrete Mathe void FügeEin(int neuerWert) { Element neuesElement = newElement(wert); neuesElement.weiter = weiter; weiter = neuesElement; wert = neuerWert; } Einfügen am Anfang einer Liste 16 Kopf kopf.FügeEin(17) A 9x 15
Diskrete Mathe void FügeEin(int neuerWert) { Element neuesElement = newElement(wert); neuesElement.weiter = weiter; weiter = neuesElement; wert = neuerWert; } Einfügen am Anfang einer Liste 16 Kopf neuesElement A 9x
Diskrete Mathe void FügeEin(int neuerWert) { Element neuesElement = newElement(wert); neuesElement.weiter = weiter; weiter = neuesElement; wert = neuerWert; } Einfügen am Anfang einer Liste 16 neuesElement 25 Kopf A 9x
Diskrete Mathe void FügeEin(int neuerWert) { Element neuesElement = newElement(wert); neuesElement.weiter = weiter; weiter = neuesElement; wert = neuerWert; } Einfügen am Anfang einer Liste 16 Kopf A 9x
Diskrete Mathe void FügeEin(int neuerWert) { Element neuesElement = newElement(wert); neuesElement.weiter = weiter; weiter = neuesElement; wert = neuerWert; } Einfügen am Anfang einer Liste Kopf A 9x
Diskrete Mathe void FügeEin(int neuerWert) { Element neuesElement = newElement(wert); neuesElement.weiter = weiter; weiter = neuesElement; wert = neuerWert; } Einfügen am Anfang einer Liste Kopf A 9x
Diskrete Mathe void FügeEin(int neuerWert) { Element neuesElement = newElement(wert); neuesElement.weiter = weiter; weiter = neuesElement; wert = neuerWert; } Einfügen am Anfang einer Liste Kopf A 9x
Diskrete Mathe void FügeEin(int neuerWert) { Element neuesElement = newElement(wert); neuesElement.weiter = weiter; weiter = neuesElement; wert = neuerWert; } Einfügen am Anfang einer Liste Kopf A 9x
Diskrete Mathe 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 Problem der bisherigen Lösung
Diskrete Mathe A 8x Die Klasse „Liste“ Liste 0..1 kopf 0..1 fuß 0..1 Element +Element(i : int) -wert : int weiter 0..1
Diskrete Mathe 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 werden („Überladung“) Die Klasse Element (vollständig) neu
Diskrete Mathe 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! Die Klasse „Liste“ leere Liste