Document

Werbung
Klausur „Diskrete
Mathematik II“
Musterlösung zu den
Vorbereitungsaufgaben
1
Aufgabe 1: Umkehren einer Liste (Pseudocode auf
hohem Niveau)
Eingabe: Eine einfach verkettete Liste
Ausgabe: Eine einfach verkettete Liste, die die Elemente er
Eingabeliste in umgekehrter Reihenfolge enthält
Programm:
Durchlaufe die Eingabeliste beginnend mit dem Kopf. Jedes Element
wird kopiert, und die Kopie wird jeweils vorne (d.h. an der
Kopfseite) in eine neue Liste eingehängt. Der Kopf der neuen Liste
ist das zuletzt eingehängte Element.
2
Aufgabe 1: Umkehren einer Liste (Alternative, eher an Java
angelehnt)
// Die folgende Lösung verwendet die Klasse "Element" aus der
// Vorlesung. Die Lösung mit "Element" und "Liste" ist analog.
Element Kopf = ...; //Kopf der zu invertierenden Liste
Element aktuell = Kopf;
Element neuerKopf = NULL; //Kopf der invertierten Liste
while( aktuell != NULL )
{
Element Neu = new Element(aktuell.Wert); //Erzeugen einer Kopie
Neu.Weiter = neuerKopf;
neuerKopf = Neu;
aktuell = aktuell.Weiter;
}
3
Aufgabe 2: Multiplikation einer Matrix mit einem Vektor
int n = ...;
//Länge des Vektors bzw. Anzahl der Spalten
int m = ...; // Anzahl der Zeilen
double [ ] vek = new double[n];
// vek ist der Vektor
double [ ][ ] mat = new double[m,n]; // mat ist die Matrix
double [] ergebnis = new double [m] ;
ergebnis = {0,0,0...}
//Produkt von vek und mat
//Initialisierung mit 0
vek = ...; mat = ...; // Belegung von vek und mat
for ( int i = 1 ; i <= m ; i++ )
for ( int j = 1 ; j <= n ; j++ )
{
ergebnis[i] = ergebnis[i] + mat[i,j] * vek[j];
}
4
Aufgabe 3: Umgekehrte Polnische Notation
Prozedur zur Erzeugung der Umgekehrten Polnischen Notation aus
einem Syntaxbaum:
upn() { upn(wurzel); }
upn(Knoten W) {
if(W = NULL) return;
print(W);
print("(");
upn(W.LinkerNachfolger);
print(",");
upn(W.RechterNachfolger);
print(")");
}
Bemerkung: Die Prozedur "upn()" ist fast identisch zu der Prozedur
"PreOrder()" (Mathe 8, 1. Semester). Dort fehlen nur die Befehle zur
Ausgabe der Klammern und des Komma (print("("); print(","); print(")")).
5
Aufgabe 4.1: Algorithmus zum Entfernen eines Knotens
aus einem binären Suchbaum:
Durchsuche den Baum solange, bis der zu löschende Knoten gefunden ist (z.B. mit
Breiten- oder Tiefensuche); dieser sei L; merke Dir den Zeiger auf L vom Vorgänger im
Baum; dieser sei zL
•
falls L keine Nachfolger hat, lösche L, setzt zL auf Null und beende die Prozedur
andernfalls suche den Ersatzknoten E für L wie folgt:
•
falls L einen linken Nachfolger hat, gehe einmal nach links und dann solange nach
rechts, wie rechte Nachfolger vorhanden sind. Der gefundene Knoten sei E.
•
falls L keinen linken Nachfolger hat, gehe einmal nach rechts und dann solange
nach links, wie linke Nachfolger vorhanden sind. Der gefundene Knoten sei E.
ersetze L durch E: dazu wird zL auf E gesetzt, und der linke und rechte Nachfolgen von L
wird dem linken und rechten Nachfolger von E zugewiesen;
lösche L und ersetze das alte Vorkommen von E durch den linken/rechten Nachfolger F
von E
6
Aufgabe 4.1: Beispiel: Löschen des Knotens mit Nr. 84 (dient nur zur
Veranschaulichung, gehört nicht zur Musterlösung)
65
zL
44
16
8
4
34
84
57
55
50 56
L
70
60
90
73
67
72
88
99
80 E 96
75 F
74
77
7
Aufgabe 4.1: Beispiel: Löschen des Knotens mit Nr. 84 (dient nur zur
Veranschaulichung, gehört nicht zur Musterlösung)
65
zL
44
16
8
4
34
80
57
55
50 56
E
70
60
90
73
67
72
74
88
75 F
99
96
77
8
Aufgabe 4.1 (Fortsetzung): Der schwierige Fall im Algorithmus ist der, dass der
zu löschende Knoten L Nachfolger hat, d.h. kein Blatt ist.
Aufgabe 4.2: Korrektheit des Algorithmus
Gezeigt werden muss, dass das Ergebnis wieder ein binärer Suchbaum ist.
Dazu muss gezeigt werden, dass die Ersetzung von L durch E und von E durch
F die Suchbaumeingenschaft nicht zerstört
• Ersetzung von L durch E: E muss der größte (kleinste) Knoten im linken
(rechten) Teilbaum unter L sein: Man betrachtet den Pfad, der von E zu L
führt. Alle Knoten auf diesem Pfad sind kleiner als E (da E links von diesen
Knoten liegt), und alle linken Teilbäume dieser Knoten sind ebenfalls
kleiner als E. Folglich ist E der größte Knoten im linken Teilbaum unter L.
Der Beweis, dass E der kleinste Knoten im rechten Teilbaum unter L ist,
verläuft analog.
• Ersetzung von E durch F: Wenn E rechter (linker) Nachfolger eines
Knotens K ist, d.h. E > K (E < K), dann ist auch jeder Knoten des
Teilbaumes unter E größer (kleiner) als K.
9
Aufgabe 5: Anwendung des Algorithmus von Dijkstra
A
30
90
100
B
40
E
40
10
20
C
10
D
10
Schritt 1
A
30
90
100
90
B
40
30
E
40
20
10
C
10
D
100
Grüner Knoten mit minimalen Kosten ist E (30)
11
Schritt 2
A
30
90
100
90
B
40
30
E
40
20
10
C
10
D
30 + 40 = 70 < 100
AEC statt AC
70
40
Grüner Knoten mit minimalen Kosten ist D (40)
12
Schritt 3
A
30
90
100
50
B
40
30
E
40
20
10
C
10
D
40
30 + 10 + 10 = 50 < 90
AEDB statt AB
70
Grüner Knoten mit minimalen Kosten ist B (50)
13
Schritt 4
A
30
90
100
50
B
40
30
E
40
10
20
C
10
D
70
30 + 40 = 70 < 30 + 10 + 10 = 70
40
AEC bleibt (statt AEDB)
Grüner Knoten mit minimalen Kosten ist C (70) 14
Schritt 5
A
30
90
100
50
B
40
30
E
40
10
20
C
10
D
70
40
15
Alternative Lösung
A
30
90
100
50
B
40
30
E
40
10
20
C
10
D
70
40
16
So könnte die Lösung auch aussehen:
Aktuell bearb.
Knoten
Liste der grünen Knoten
(A,0)
(A,0)
(E,30), (C,100), (B,90)
(E,30)
(D,40), (C,70), (B,90)
(D,40)
(C,70), (B,50)
(B,50)
(C,70)
(C,70)
17
Aufgabe 6: Dijkstra: Unterscheidung
Entfernung und Fahrzeit
• Beides sind Kosten
• Zwei Attribute an Kanten; Dijkstra muss
wissen, welches verwendet werden soll
18
Aufgabe 7.1: Heap
7
22
9
23
11
27
30
90
28
7 22
9 23 27 11 30 90 28 33 80 19 7019
33
80
19
70
Aufgabe 7.2:
7
9
22
27
23
90
7 22
28
33
11
80
19
30
70
8
9 23 27 11 30 90 28 33 80 19 7020 8
Aufgabe 7.2:
7
22
9
27
23
90
7 22
28
33
9 23 27 11
11
80
19
8
70
30
8 90 28 33 80 19 7021 30
Aufgabe 7.2:
7
8
22
27
23
90
7 22
28
33
8 23 27 11
11
80
19
9
70
30
9 90 28 33 80 19 7022 30
Aufgabe 7.3: Wie gut ist Array-Repräsentation
auch für AVL-Bäume geeignet?
Nicht gut.
• Lücken in Array (AVL-Baum nicht
ausgeglichen)
• Einfügen/Löschen von Knoten erfordert
Rotationen: Fast jedes Arrayelement
muss verschoben werden: O(n)
=> Beispiel L-Rotation (die folgende Animation ist zur Lösung
der Aufgabe nicht erforderlich; sie dient nur der Veranschaulichung)
23
L-Rotation
+1
k1
0
k2
T1
T2
T3
24
L-Rotation: Einfügen von x
+2
k1
+1
k2
T1
T2
T3
x
25
L-Rotation
+2
k1
+1
k2
T1
T2
T3
x
26
L-Rotation
k1 +2
+1
k2
T1
T2
T3
x
27
L-Rotation
0
k2
k1
0
T3
T1
T2
x
28
L-Rotation
Position jedes
Arrayelements
verändert
0
k2
k1
0
T3
T1
T2
x
29
Aufgabe 8: Zusammenhang eines Graphen
4 Alternative Lösungen:
• Tiefensuche: Graph zusammenhängend, wenn alle Knoten durchlaufen
werden
• Breitensuche (wie Tiefensuche)
• Dijkstra (beliebige Kosten > 0, wie Tiefensuche)
• Floyd (beliebige Kosten > 0), Graph zusammenhängend, wenn kein  in
Matrix
Ein Problem ergibt sich daraus, dass die Definition "zusammenhängend" in der
Aufgabenstellung von ungerichteten Graphen ausgeht, die vier Verfahren
jedoch von gerichteten. Der unten gezeigte gerichtete Graph ist
zusammenhängend; mit Startknoten B würde jedoch Dijkstra niemals A
erreichen. Eine Lösung dieses Problems besteht darin, bei gerichteten
Graphen zu jeder Kante eine Kante mit entgegengesetzter Orientierung zu
ergänzen. Ungerichtete Kanten müssen durch zwei gerichtete Kanten mit
entgegengesetzter Orientierung ersetzt werden.
A
30
B
Aufgabe 9: Anwendung von Scan-Line
A
D
B
Schnittpunkt
erkannt
(bereits
vorhanden)
C
D
DA A
CD D
C B
C
A
D
C
A
C
D
A C
C A
A
31
Herunterladen