institut für kartographie und geoinformation prof. dr. lutz plümer diskrete mathematik i vorlesung...
Post on 05-Apr-2015
106 Views
Preview:
TRANSCRIPT
Institut für Kartographie und GeoinformationProf. Dr. Lutz Plümer
Diskrete Mathematik IVorlesung 5
11.11.99
-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 Festlegungauf 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
Element 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
3 7
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 oderkein 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 dasaufrufende 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);}
lauf25
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);}
22
25
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
22
25
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);}
22
25
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);}
22
25
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
22
25 28
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);}
28
22
25
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);}
28
22
25
kopf
27
15 22 28
15 22 2817
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
29
25 22 28kopf
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
30
25 22 28kopf
void FügeEin(int neuerWert){ Element neuesElement = newElement(wert); neuesElement.weiter = weiter; weiter = neuesElement; wert = neuerWert;}
25neuesElement
Einfügen am Anfang einer Liste
31
25 22 28kopf
void FügeEin(int neuerWert){ Element neuesElement = newElement(wert); neuesElement.weiter = weiter; weiter = neuesElement; wert = neuerWert;}
neuesElement
Einfügen am Anfang einer Liste
25
32
25 22 28kopf
void FügeEin(int neuerWert){ Element neuesElement = newElement(wert); neuesElement.weiter = weiter; weiter = neuesElement; wert = neuerWert;}
Einfügen am Anfang einer Liste
25
33
25 22 28kopf
void FügeEin(int neuerWert){ Element neuesElement = newElement(wert); neuesElement.weiter = weiter; weiter = neuesElement; wert = neuerWert;}
Einfügen am Anfang einer Liste
25
34
25 22 28kopf
void FügeEin(int neuerWert){ Element neuesElement = newElement(wert); neuesElement.weiter = weiter; weiter = neuesElement; wert = neuerWert;}
25
Einfügen am Anfang einer Liste
35
17 22 28kopf
void FügeEin(int neuerWert){ Element neuesElement = newElement(wert); neuesElement.weiter = weiter; weiter = neuesElement; wert = neuerWert;}
25
Einfügen am Anfang einer Liste
36
17 22 28kopf
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
Liste0..1
kopf
0..1fuß
0..1
0..1Element
+Element(i : int)
-wert : intweiter
0..1
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
leere Liste
Die Klasse „Liste“
top related