1. Übung Algorithmentechnik Institut für Theoretische Informatik 04.11.2008 1/ 42
Aufgabe 1 Aufgabe (Amortisierte Analyse) Modellieren Sie eine Queue mit zwei Stacks so, dass die amortisierten Kosten von Dequeue und Enqeue jeweils in O(1) sind. Geben Sie die Operationen Dequeue und Enqueue in Pseudocode an und begründen Sie die amortisierten Kosten. 2/ 42
Aufgabe 1 globale Datenstruktur: zwei Stacks E und D, die initial leer sind E wird für Enqueue benutzt D wird für Dequeue benutzt betrachten Folge von n Enqueue- und Dequeue-Operationen für Analyse 3/ 42
1 Algorithmus 1 : Enqueue(x) Push(E,x) Aufwand 1 = O(1) Aufgabe 1 O(1) 1 2 3 4 Algorithmus 2 : Dequeue() wenn D = dann solange E tue Push(D,Pop(E)) pop(d) Aufwand 1 bzw. 2 E + 1 = O( E ) O(1) 4/ 42
Korrektheit betrachte Folge von Insert und Dequeue x 1 x 2 x k D 1 x k+1 x r D k zu Beginn seien D, E leer vor D 1 liegen x 1 x 2 x k in umgekehrter Reihenfolge des Einfügens auf E nach D 1 ist E leer und auf D liegen x k x 1 in Reihenfolge des Einfügens D 1,..., D k entfernen jeweils x 1,..., x k in der Reihenfolge des Einfügens d.h. D i entfernt x i vor D k+1 liegen x k+1 x s auf E und D ist leer nach D k+1 liegen x s x k+1 auf D und D k+1,..., D s entfernen jeweils x k+1,..., x s... 5/ 42
Ganzheitsmethode wenn Dequeue Aufwand von E verursacht, dann müssen vorher E Enqueue-Operationen stattgefunden haben Gesamtaufwand für Dequeue-Operationen ist höchstens so groß wie Gesamtaufwand für Enqueue-Operationen, d.h. O(n) Gesamtaufwand T (n) = O(n) Aufwand pro Operation T (n)/n = O(1) 6/ 42
Buchungsmethode definieren Kosten wie folgt tatsächliche Kosten amortisierte Kosten Enqueue 1 3 Dequeue 1, E 1 Idee: beim Einfügen bezahlt jedes Element das Einfügen in E sofort und hinterlegt Kredit von 2 für Hinzufügen zu D (1 Pop, 1 Push) amortisierte Kosten in O(1) 7/ 42
Potentialmethode sei D i Datenstruktur nach i-ter Operation, Datenstruktur sei zu Beginn leer definiere Potential Φ : D i Φ(D i ) := 2 E Φ(D O ) = 0, Φ(D i ) Φ(D 0 ) im Folgenden ĉ i : amortisierte Kosten, c i reale Kosten der i-ten Operation dann gilt ĉ i := c i + Φ(D i ) Φ(D i 1 ) 8/ 42
Potentialmethode i-te Operation ist Enqueue mit E := k: ĉ i = c i + Φ(D i ) Φ(D i 1 ) = 1 + 2(k + 1) 2k = 3 i-te Operation ist Dequeue mit D > 0, E := k: ĉ i = c i + Φ(D i ) Φ(D i 1 ) = 1 + 2k 2k = 1 i-te Operation ist Dequeue mit D = 0, E := k: ĉ i = c i + Φ(D i ) Φ(D i 1 ) = 2k + 1 + 0 2k = 1 9/ 42
Aufgabe 2 Aufgabe (Untere Schranken) Gegeben sei eine Folge (a i ) n i=1 von n Elementen. Zeigen Sie, dass man mindestens Ω(log n) Vergleiche benötigt, um den Index i max des maximalen Elementes a imax bestimmen. zu 10/ 42
Problemstellung sei Π ein Problem Untere Schranken finde eine Funktion l : N N (untere Schranke für Π) mit folgender Eigenschaft: jeder Algorithmus A, der Π löst, hat eine worst-case Komplexität T A (n) Ω(l(n)), d.h. kein Algorithmus mit Komplexität T A (n) o(l(n)) Problem: Aussage über alle Algorithmen schwierig Festlegung eines Algorithmen-Modells durch sog. Entscheidungsbäume Komplexitätsmaß ist Anzahl der Entscheidungen 11/ 42
Entscheidungsbäume als Algorithmen-Modell Algorithmus als Baum mit konstantem Maximalgrad nicht-uniformes Modell, d.h. unterschiedliche Bäume für Instanzen unterschiedlicher Größe Knoten ist Orakel, das zu jeder Instanz einen Kindknoten ausgibt Blätter sind mit Ausgabe des Algorithmus annotiert Berechnung: Weg von der Wurzel zu einem Blatt (gemäß Orakelspruch ) Komplexität einer Berechnung: Länge des Weges Komplexität des Algorithmus: Höhe des Baumes 12/ 42
Entscheidungsbäume als Algorithmen-Modell 13/ 42
Entscheidungsbäume als Algorithmen-Modell sei h Höhe des Baumes und n die Anzahl der Blätter und k Maximalgrad dann gilt n k h, d.h. h log k n Annahme: Algorithmus A habe n verschiedene Ausgaben Baum hat mind. n Blätter Höhe des Baumes ist mind. log k n Informationstheoretische Begründung: benutze Weg, um Ausgabe zu kodieren: Bei Höhe h und Maximalgrad k kann es höchstens n = k h verschiedene Ausgaben (Blätter) geben log k n ist (triviale) untere Schranke 14/ 42
Erster Ansatz Algorithmus für das Maximum-Problem hat n verschiedene Ausgaben log 2 n ist untere Schranke, falls nur Vergleiche zugelassen sind diese Schranke ist scharf! verwende binären Suchbaum als Algorithmus imax < n/2 imax < n/4 imax < 3n/4 imax < n/8 imax < 3n/8 imax < 5n/8 imax < 7n/8 15/ 42
Anderer Ansatz Problem mit erstem Ansatz: ein Algorithmus, der Index des maximalen Elements nicht kennt, kann Orakelfrage nicht beantworten Modell ist zu mächtig Einschränkung: Jede Anfrage muss von der Form x i < x j sein sei T Entscheidungsbaum in diesem Modell für das Maximum-Problem mit n Elementen wir konstruieren Eingabe, bei der der Algorithmus möglichst viele Vergleiche anstellen muss (Adversary-Argument) 16/ 42
Adversary Argument zunächst nehmen wir an, dass x i = i für alle i falls Algorithmus Anfrage x i < x j stellt, markieren wir x i Markierung bedeutet: Algorithmus weiß, dass x i nicht das maximale Element ist x n wird nicht markiert (da es das größte Element ist) Annahme: x k (k n) werde ebenfalls nicht markiert (d.h. Algorithmus macht weniger als n 1 Vergleiche) Algorithmus kann nicht unterscheiden, ob x k oder x n Maximum ist bei Ausgabe x n wählen wir x k := n + 1 sonst belassen wir die Folge (konsistent mit Anfragen) mindestens n 1 Vergleiche nötig 17/ 42
Aufgabe 3 Aufgabe (Laufzeit rekursiver Funktionen) Bestimmen Sie den größten ganzzahligen Wert a mit der Eigenschaft, dass ein Algorithmus mit der durch T B (n) = a T B (n/4) + n 2 bestimmten Laufzeit im Θ-Kalkül asymptotisch schneller ist, als ein Algorithmus mit der durch bestimmten Laufzeit. T A (n) = 7 T A (n/2) + n 2 18/ 42
Theorem (Master-Theorem) Master-Theorem Seien a 1 und b > 1 Konstanten, f (n) eine Funktion in n und T (n) über nichtnegative ganze Zahlen definiert durch dann gelten T (n) = a T (n/b) + f (n), a (i) T (n) Θ(f (n)) falls f (n) Ω(n log b a+ε ) und af ( n b ) cf (n) für eine Konstante c < 1 und n n 0, (ii) T (n) Θ(n log b a log n) falls f (n) Θ(n log b a ), (iii) T (n) Θ(n log b a ) falls f (n) O(n log b a ε ). a Dabei stehen n/b für n/b oder n/b. 19/ 42
Aufgabe 4 Aufgabe (Das Tiefen-Bestimmungs-Problem) Entwerfen Sie eine Datenstruktur, die eine Menge F von disjunkten Bäumen verwaltet und folgende Operationen unterstützt. Make-Tree(v): erzeuge neuen Baum mit Wurzel v Attach(r, v): hänge Baum mit Wurzel r an Knoten v an Find-Depth(v): bestimme Tiefe von v 20/ 42
Makeset 1 Algorithmus 3 : Makeset(x) (#2) Eingabe : Element x Vor[x] 1 Die Laufzeit ist in O(1). 21/ 42
Weighted Union Algorithmus 4 : Union(i, j) (#3) 1 2 3 4 5 z Vor[i] + Vor[j] wenn Vor[i] < Vor[j] dann Vor[i] j und Vor[j] z sonst Vor[j] i und Vor[i] z Die Laufzeit ist in O(1). 22/ 42
1 2 3 4 5 6 7 8 9 Find mit Pfadkompression Algorithmus 5 : Find(x) (#3) Eingabe : Element x Ausgabe : Menge, in der x enthalten ist j x solange Vor[j] > 0 tue j Vor[j] i x solange Vor[i] > 0 tue temp i i Vor[i] Vor[temp] j Gib j aus Die Laufzeit ist in O(log n). Repräsentanten-Suche Pfadkompression 23/ 42
Modifikation von Union-Find Modifikation zur Verwaltung der Tiefe (Struktur der Bäume muss nicht durch Union-Find verwaltet werden) Annotation der Knoten mit Wert d(v), der folgende Eigenschaft hat sei v k := Find(v 0 ) sei v 0, v 1, v 2,..., v k die Folge von Knoten, die Find(v 0 ) von v 0 zur Wurzel v k durchläuft dann soll gelten: Tiefe von v 0 ergibt sich als k i=0 d(v i) d(v i ) ist also Differenz zwischen Tiefe von v i und v i+1 (direkter Vorgänger) 24/ 42
Korrektheit es gilt d(v i ) := Find-Depth(v i ) Find-Depth(v i+1 ) (i < k) d(v k ) := Find-Depth(v k ) Summe ist Teleskop-Summe, d.h. k d(v i ) = Find-Depth(v 0 ) i=0 stelle sicher, dass obige Gleichungen immer erfüllt sind 25/ 42
Makeset 1 2 Algorithmus 6 : Make-Tree(x) Eingabe : Knoten x Ausgabe : Neuer Baum mit Wurzel x d[x] 0 Vor[x] 1 Korrektheit ist klar. 26/ 42
1 2 3 4 5 6 7 8 9 10 11 12 13 14 Algorithmus 7 : Find(x) Eingabe : Knoten x Ausgabe : Das Paar (Depth, r) (Tiefe und Wurzel von x) r x Repräsentanten-Suche Depth d[x] solange Vor[r] > 0 tue r Vor[r] Depth Depth + d[r] i x PDepth 0 solange Vor[i] > 0 tue t d[i] d[i] Depth PDepth d[r] PDepth PDepth + t temp i i Vor[i] Vor[temp] r Pfadkompression 27/ 42
Korrektheit sei v 0,..., v k Folge, die Find durchläuft, d.h. x = v 0 Zeile 9/10 d[v i ] Depth PDepth d[r] Depth=Find-Depth(x) und hat Wert k s=0 d alt[s] PDepth hat Wert i 1 s=0 d alt[s] im i-ten Schritt d neu [v i ] = k d alt [s] d alt [r] s=i = Find-Depth(v i ) d alt [r] = Find-Depth(v i ) Find-Depth(r) 28/ 42
1 2 3 4 5 6 7 8 9 10 Algorithmus 8 : Attach(r, x) (modifiziertes Union) Eingabe : Wurzel r eines Baumes und ein Knoten x Ausgabe : Der Knoten r wird an x angehängt (d x, q x ) Find(x) (d r, q r ) Find(r) z Vor[q x ] + Vor[q r ] wenn Vor[q r ] < Vor[q x ] dann q x wird Wurzel Vor[q r ] q x und Vor[q x ] z d(q r ) d(q r ) + d x + 1 d(q x ) sonst q r wird Wurzel Vor[q x ] q r und Vor[q r ] z d(q r ) d(q r ) + d x + 1 d(q x ) d(q x ) d(q r ) 29/ 42
Korrektheit q x q x wird Wurzel q r x r d(q r ) d(q r ) + d x + 1 d(q x ) 30/ 42
Korrektheit q x q x wird Wurzel q r wird Wurzel q r q r q x x r r x d(q r ) d(q r ) + d x + 1 d(q x ) d(q r ) d(q r ) + d x + 1 d(q x ) d(q x ) d(q r ) 30/ 42
1 2 Algorithmus 9 : Find-Depth(x) Eingabe : Knoten x Ausgabe : Die Tiefe Depth(x) von x (d, r) Find(i) Depth(x) d 31/ 42
Aufgabe 5 Aufgabe (Berechnung starker Zusammenhangskomponenten) Gegeben sei ein gerichteter Graph D = (V, E). für u, v V gelte u v, wenn es einen gerichteten Weg von u nach v und einen gerichteten Weg von v nach u gibt Zeigen Sie, dass eine Äquivalenzrelation ist. Die Äquivalenzklassen zu heißen starke Zusammenhangskomponenten. Schreiben Sie einen Algorithmus in Pseudocode, der die starken Zusammenhangskomponenten findet. 32/ 42
Äquivalenzrelation Reflexivität: u u, da Weg der Länge 0 existiert Symmetrie: u v v u, nach Definition Transitivität: u v, v w u w: da Weg von u über v nach w und umgekehrt existiert Bemerkung: u w gdw. u und v liegen auf einem gerichteten Kreis 33/ 42
Tiefensuche 1 2 3 4 5 6 Algorithmus 10 : DFS(G=(V,E)) für v V tue π(w) Nil Color[v] White für v V tue wenn Color[v] = White dann DFS-Visit(v) 34/ 42
1 2 3 4 5 Algorithmus 11 : DFS-Visit(v, S) Color[v] Gray für (v, w) E tue wenn Color[w] = White dann π(w) v Mod-DFS-Visit(w, S) neuer Knoten 6 Color[v] Black 35/ 42
Ineffizienter Algorithmus 1 2 3 4 5 6 7 8 Algorithmus 12 : Starke-Zusammenhangskomponenten-1 für v V tue Makeset(v) für {v, w} 2 V tue wenn Find(v) Find(w) dann Dfs-Visit(v) Dfs-Visit(w) wenn w Dfs-Visit(v) und v Dfs-Visit(w) dann Union(Find(v), Find(w)) Aufwand O(n 3 )! 36/ 42
modifizierte Tiefensuche Vorgehensweise verwalte Mengen von äquivalenten Knoten mit Union-Find falls Tiefensuche Kreis findet, können alle Knoten auf dem Kreis kontrahiert werden verwenden Stack S für Repräsentanten von Mengen äquivalenter Knoten mit der Eigenschaft, dass einer der Knoten auf dem aktuell offenen Pfad der Tiefensuche liegt 37/ 42
modifizierte Tiefensuche 1 2 3 4 5 6 7 Algorithmus 13 : Starke-Zusammenhangskomponenten Daten : Stack S für v V tue Makeset(v) π(w) Nil Color[Find(v)] White für v V tue wenn Color[Find(v)] = White dann Mod-DFS-Visit(v) 38/ 42
1 2 3 4 5 6 7 8 9 Algorithmus 14 : Mod-DFS-Visit(v, S) Color[Find(v)] Gray wenn Find(v) Find(Peek(S)) dann Push(S, v) für (v, w) E tue wenn Color[Find(w)] = White dann π(w) v Mod-DFS-Visit(w, S) sonst wenn Color[Find(w)] = Gray dann Kontrahiere-Kreis(w, S) neuer Knoten Kreis gefunden 10 11 12 wenn Find(π(v)) Find(Peek(S)) dann Color[Find(v)] Black Pop(S) Stack aufräumen 39/ 42
1 2 3 4 5 6 Algorithmus 15 : Kontrahiere-Kreis(w, S) x Pop(S) solange Find(w) Find(x) tue Union(Find(w), Find(x)) x Pop(S) Color[Find(w)] Grey Push(S, w) 40/ 42
Beispiel 1 2 3 4 5 6 {1} Stack 41/ 42
Beispiel 1 2 3 4 5 6 {4} {1} Stack 41/ 42
Beispiel 1 2 3 4 5 6 {2} {4} {1} Stack 41/ 42
Beispiel 1 2 3 4 5 6 {3} {2} {4} {1} Stack 41/ 42
Beispiel 1 2 3 4 5 6 {3} {2} {4} {1} {1, 2, 4} Stack 41/ 42
Beispiel 1 2 3 4 5 6 {3} {2} {4} {1} {1, 2, 4} Stack 41/ 42
Beispiel 1 2 3 4 5 6 {3} {2} {4} {5} {1} {1, 2, 4} Stack 41/ 42
Beispiel 1 2 3 4 5 6 {3} {2} {4} {5} {1} {1, 2, 4} 4, 5} Stack 41/ 42
Beispiel 1 2 3 4 5 6 {3} {2} {4} {5} {6} {1} {1, 2, 4} 4, 5} Stack 41/ 42
Beispiel 1 2 3 4 5 6 {3} {2} {4} {5} {6} {1} {1, 2, 4} 4, 5} 5, 6} Stack 41/ 42
Beispiel 1 2 3 4 5 6 {3} {2} {4} {5} {6} {1} {1, 2, 4} 4, 5} 5, 6} Stack 41/ 42
Korrektheit Algorithmus durchläuft Graph mit Tiefensuche sei v 1,..., v k der aktuelle Tiefensuche-Pfad Stackinhalt: w 1,..., w k mit Find(v i ) = Find(w i ) d.h. Stack enthält zu jedem Zeitpunkt für jeden Knoten v auf dem aktuell offenen Pfad den Repräsentanten einer Menge, die v enthält sei C gerichteter Kreis in G die Knoten auf C werden zu einer Menge zusammengefasst Menge wird erst schwarz gefärbt, wenn alle Knoten in der Menge abgesucht wurden 42/ 42