Notizen Algorithmen und Datenstrukturen (für ET/IT) Sommersemester 2016 Dr. Tobias Lasser Computer Aided Medical Procedures Technische Universität München Programm heute Notizen 7 Fortgeschrittene Datenstrukturen 8 Such-Algorithmen 9 Graph-Algorithmen Tiefensuche Breitensuche 8 Bild-Repräsentation mit Pixeln Notizen • Bild als zwei-dimensionales Feld • einzelnes Element: Pixel (picture element) • hier: jedes Pixel hat einen Grauwert zugewiesen • z.B. von 0 bis 255 9 Segmentierung von Bildern Notizen • Segmentierung: Zusammenfassung von inhaltlich zusammenhängenden Regionen gemäß eines Kriteriums • Beispiel: Segmentierung von Knochen oder Organen 10 Binäre Bilder Notizen • Binäres Bild: jedes Pixel hat entweder Wert 0 oder 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 1 1 0 0 0 1 0 0 1 1 1 1 1 0 1 1 1 0 0 1 1 1 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 • Segmentierungs-Problem: identifiziere die beiden “Sterne” → Algorithmus? 11 Problem: Segmentierung von “Sternen” 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 1 1 0 0 0 1 0 0 1 1 1 1 1 0 1 1 1 0 0 1 1 1 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 Notizen • Gegeben: binäres Bild mit 0,1 Werten • Gesucht: Regionen im Bild mit nur 1 Werten • Ansatz: • fange an bei Pixel mit Wert 1 • wiederhole: inspiziere unbesuchte Nachbar-Pixel auf Wert 1 • beende falls kein weiterer Nachbar mit Wert 1 existiert 12 Nachbarschaft von Pixeln Notizen N N P N N 4-Nachbarschaft N N N N P N N N N 8-Nachbarschaft • 4-Nachbarschaft von Pixel P: alle direkten Nachbar-Pixel, die Kante mit P gemeinsam haben • auch genannt: Von-Neumann-Nachbarschaft • 8-Nachbarschaft von Pixel P: alle direkten Nachbar-Pixel, die Kante oder Ecke mit P gemeinsam haben • auch genannt: Moore-Nachbarschaft 13 “Stern” als Graph Notizen 1 5 2 3 4 6 7 8 10 11 12 9 13 Segmentierungs-Ansatz von linkem “Stern”: 1 starte mit Pixel 1 2 besuche Nachbarn (Schema: oben, unten, links, rechts) 14 Segmentierungs-Durchlauf als Baum Notizen 1 1 5 3 2 3 4 6 7 8 10 11 12 7 11 9 13 10 12 6 8 13 2 5 4 9 Ansatz auch genannt: Tiefensuche bzw. Depth-First Search (DFS) 15 Tiefensuche (DFS) Notizen Sei G = (V , E ) Graph (gerichtet oder ungerichtet). • Graph repräsentiert mit Adjazenzliste adj • jeder Knoten hat Farb-Markierung farbe: • weiss = noch nicht besucht • grau = besucht, gerade in Bearbeitung • schwarz = besucht, fertig bearbeitet • jeder Knoten hat Vorgänger in Besuch-Reihenfolge pred • (optional) zusätzliche Knoten-Markierungen d und f • Zeitmarke, wann Knoten entdeckt: d (discovered) • Zeitmarke, wann Knoten fertig bearbeitet: f (finalized) 16 Algorithmus DFS Notizen Input: Graph G = (V , E ) Output: Vorgänger-Liste pred, Markierungen d, f DFS(G ): for each (Knoten v ∈ V ) { farbe[v ] = weiss; pred[v ] = null; } zeit = 0; for each (Knoten v ∈ V ) { if (farbe[v ] == weiss) DFSvisit(v ); } DFSvisit(v ): farbe[v ] = grau; // v war weiss zeit = zeit + 1; d[v ] = zeit; for each (Knoten u ∈ adj[v ]) { if (farbe[u] == weiss) { pred[u] = v; DFSvisit(u); } } farbe[v ] = schwarz; // v ist fertig zeit = zeit + 1; f[v ] = zeit; 17 DFS: Beispiel-Ablauf 1 Notizen u v w x y z • Knoten u, v, w, x, y, z • farbe direkt im Knoten markiert • d/f im Knoten notiert • pred markiert durch rote Kanten 18 DFS: Beispiel-Ablauf 2 u v w Notizen u v 1/_ 1/_ w u v 2/_ 1/_ w 2/_ 3/_ x y u v 1/_ z x w u y v 2/_ 1/_ z x w u y v 2/_ 1/_ 4/_ 3/_ u v 1/_ z x w u 3/_ 4/5 y v 2/_ 1/_ B z x w u 3/6 z 1/_ 3/6 B 4/5 y z w 2/7 F x z v 2/7 4/5 y 3/_ y B 4/5 x B 4/_ y w 2/_ B x z 3/6 x y z 19 DFS: Beispiel-Ablauf 3 u v 1/_ F F 3/6 z v 1/8 B 4/5 z v 1/8 F 4/5 z 10/ 11 B 9/_ C B 4/5 x w 2/7 3/6 y z 10/ _ B w 9/ 12 2/7 C B 4/5 x z v 1/8 F 3/6 y y u 9/_ C B 3/6 x w 2/7 F 10/ _ z v 1/8 C B 3/6 y u 9/_ 9/_ B x w w 2/7 4/5 z 2/7 4/5 y u 3/6 v F 3/6 x F 1/8 C v 1/8 y u 9/_ u B x w 2/7 w 2/7 4/5 y u v 1/8 B 4/5 F u 2/7 x x w Notizen 3/6 y z 10/ 11 B 20 Spannwald mit DFS Notizen Sei G = (V , E ) Graph. • Spannbaum: Teilgraph G 0 = (V , E 0 ), der ein Baum ist und alle Knoten von G enthält. • existiert nur für zusammenhängende Graphen • Spannwald: Teilgraph G 0 = (V , E 0 ), dessen Zusammenhangskomponenten jeweils Spannbäume der Zusammenhangskomponenten von G sind • DFS erzeugt Spannwald • Knoten sind V , Kanten E 0 ergeben sich aus pred • im Beispiel-Ablauf: Knoten V sind schwarz, Kanten E 0 sind rot • DFS erlaubt Markierung spezieller Kanten: • Rückkanten im Spannwald (markiert mit B) • Vorwärtskanten im Spannwald (markiert mit F) • Cross-Kanten im Spannnwald (markiert mit C) 21 Komplexität von DFS Notizen • DFS erste Schleife wird |V | mal durchlaufen: Θ(|V |) • DFSvisit wird für jeden Knoten genau einmal aufgerufen (zweite Schleife in DFS, rekursiver Aufruf in DFSvisit) • innere Schleife in DFSvisit wird |adj(v )| mal aufgerufen X |adj(v )| = Θ(|E |) v ∈V • Gesamtlaufzeit: Θ(|V | + |E |) • Implementierung gleicher Komplexität auch nicht-rekursiv möglich (mit Stack) 22 Anwendungen von DFS Notizen • Test auf Zusammenhang von Graphen • rufe DFSvisit nur für einen Knoten auf (statt für alle) • falls nicht alle Knoten dadurch besucht: nicht zusammenhängend! • Test auf Zyklenfreiheit in Graphen • Zyklus entdeckt falls Rückkante B gefunden • Rückkante B: in DFSvisit Schleife ist Zielknoten bereits grau 23 Beispiel DFS 1 Notizen 2/_ 1/_ 1/_ 2/_ 1/_ 2/_ 3/_ 2/_ 1/_ 1/_ 4/5 3/_ 4/_ 3/_ 2/_ 1/_ 4/5 3/6 24 Beispiel DFS 2 Notizen 2/_ 4/5 1/_ 3/6 F 2/_ 1/_ 4/5 3/6 8/_ F 2/7 1/_ 4/5 3/6 F 2/7 1/_ 9/_ 4/5 3/6 9/_ 8/_ 10/ _ 8/_ F 2/7 1/_ 4/5 3/6 F 2/7 1/_ 4/5 3/6 25 Beispiel DFS 3 Notizen 9/_ 9/_ 10/ _ 8/_ F 2/7 1/_ 4/5 3/6 1/_ 10/ _ F 2/7 1/_ 1/_ 3/6 B 8/_ C 4/5 3/6 1/_ 10/ 11 8/ 13 10/ 11 F 2/7 9/ 12 C 4/5 3/6 9/ 12 B 2/7 4/5 9/_ B 8/_ 10/ _ F 2/7 9/_ 8/_ B 8/_ F C 3/6 4/5 B 2/7 1/_ 10/ 11 F C 4/5 3/6 26 Beispiel DFS 4 Notizen 9/ 12 9/ 12 B 8/ 13 10/ 11 F 2/7 1/_ C 4/5 9/ 12 1/ 14 4/5 10/ 11 F 2/7 1/ 14 F 16/ 17 C 16/ _ C 15/ _ B 8/ 13 10/ 11 F 2/7 4/5 1/ 14 3/6 4/5 3/6 9/ 12 15/ _ B 10/ 11 1/ 14 9/ 12 8/ 13 15/ _ B 2/7 3/6 4/5 3/6 8/ 13 C C 9/ 12 10/ 11 F 2/7 F 2/7 15/ _ B 10/ 11 1/ 14 3/6 8/ 13 B 8/ 13 16/ 17 C 4/5 18/ _ 3/6 27 Beispiel DFS 5 Notizen 9/ 12 15/ _ B 8/ 13 10/ 11 F 2/7 1/ 14 16/ 17 C 18/ _ 8/ 13 2/7 1/ 14 16/ 17 C 3/6 16/ 17 C C 2/7 C 18/ 19 1/ 14 18/ _ 15/ 20 B 8/ 13 4/5 4/5 3/6 9/ 12 10/ 11 F 10/ 11 F 2/7 15/ _ B 15/ _ B 8/ 13 4/5 3/6 9/ 12 1/ 14 9/ 12 10/ 11 F 16/ 17 C 3/6 4/5 C 18/ 19 28 Programm heute Notizen 7 Fortgeschrittene Datenstrukturen 8 Such-Algorithmen 9 Graph-Algorithmen Tiefensuche Breitensuche 29 Breitensuche im “Stern”-Beispiel Notizen • Segmentierung von “Sternen” 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 1 1 0 0 0 1 0 0 1 1 1 1 1 0 1 1 1 0 0 1 1 1 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 • neuer Ansatz: • anstatt direkt nächsten Nachbar ansteuern, erst alle aktuellen Nachbarn abarbeiten → Breitensuche 30 Breitensuche im “Stern”-Beispiel: Ablauf Notizen 1 5 2 3 4 6 7 8 10 11 12 9 13 1 starte mit Pixel 1 2 besuche alle Nachbarn von aktuellem Pixel (Schema: oben, unten, links, rechts) 3 arbeite die Nachbarn der Nachbarn in selber Reihenfolge ab 31 Breitensuche im “Stern”-Beispiel: als Baum Notizen 1 1 5 3 2 3 4 6 7 8 10 11 12 7 9 11 13 10 12 2 6 8 5 9 4 13 Ansatz: Breitensuche bzw. Breadth-First Search (BFS) 32 Breitensuche (BFS) Notizen Sei G = (V , E ) zusammenhängender Graph (gerichtet oder ungerichtet). • Startknoten s ∈ V • Graph repräsentiert mit Adjazenzliste adj • jeder Knoten hat Farb-Markierung farbe: • weiss = noch nicht besucht • grau = besucht, gerade in Bearbeitung • schwarz = besucht, fertig bearbeitet • jeder Knoten hat Vorgänger in Besuch-Reihenfolge pred • (optional) zusätzliche Knoten-Markierung d • Distanz (in Anzahl von Kanten) von Startknoten s • Hilfsmittel: Queue Q 33 Algorithmus BFS Notizen Input: Graph G = (V , E ), Startknoten s ∈ V Output: Vorgänger-Liste pred, Markierung d BFS(G , s): for each (Knoten v ∈ V ) { // Initialisierung farbe[v ] = weiss; pred[v ] = null; d[v ] = ∞; } farbe[s] = grau; d[s] = 0; Q = initialize(); Q.enqueue(s); while ( !Q.isEmpty() ) { u = Q.dequeue(); for each (v ∈ adj[u]) { // besuche alle Nachbarn if (farbe[v ] == weiss) { farbe[v ] = grau; d[v ] = d[u] + 1; pred[v ] = u; Q.enqueue(v ); } } farbe[u] = schwarz; // u ist erledigt } 34 BFS: Beispiel-Ablauf 1 Notizen r s t u v w x y • Knoten r, s, t, u, v, w, x, y • farbe direkt im Knoten markiert • d im Knoten notiert • pred markiert durch rote Kanten • Startknoten s 35 BFS: Beispiel-Ablauf 2 r s ∞ t 0 u ∞ r ∞ ∞ ∞ w r s 1 ∞ x ∞ ∞ v u 2 ∞ v 1 w r s 1 2 x 2 1 w 2 v 2 v t v Q: v u y u 3 2 x x ∞ 2 1 w t y u ∞ y Q: ∞ 2 0 r u x s 1 w ∞ 2 1 w r 3 x t 0 Q: y x u 2 x t v Q: v r ∞ 2 ∞ ∞ x s 1 y t 0 u ∞ 1 w r ∞ Q: t 0 s y t 0 s 1 Q: v Notizen 3 y 36 BFS: Beispiel-Ablauf 3 r s 1 t 0 u 2 r 3 2 1 w r s 1 2 x 2 2 1 w r 3 2 x s 1 t 0 u y 3 y u 2 3 y Q: 3 y u 2 Q: 3 2 x t 0 y v u 2 1 w u 3 Q: v v y t 0 s 1 Q: v Notizen 2 v 1 w 2 x 3 y 37 BFS Eigenschaften Notizen Sei G = (V , E ) Graph. • BFS erzeugt Spannbaum G 0 = (V , E 0 ) • Knoten sind V , Kanten E 0 ergeben sich aus pred • im Beispiel-Ablauf: Knoten V sind schwarz, Kanten E 0 sind rot • ausgehend von Startknoten s wird nur Zusammenhangskomponente von Graph durchsucht! • falls G nicht zusammenhängend, wird kein Spannwald berechnet! • falls Stack statt Queue in BFS: DFS-artiger Algorithmus • Unterschied: nur in Zusammenhangskomponente 38 Komplexität von BFS Notizen • BFS erste Schleife (for) wird |V | mal durchlaufen: Θ(|V |) • zweite geschachtelte Schleife (while und for) wird im schlechtesten Fall je einmal für jeden Knoten in Adjazenzliste aufgerufen X |adj(v )| = Θ(|E |) v ∈V • Gesamtlaufzeit: Θ(|V | + |E |) 39 Anwendungen von BFS Notizen • Besuche alle Knoten in Zusammenhangskomponente von Graph • ausgehend von Startknoten s • Berechne Länge der kürzesten Pfade (d.h. Anzahl von Kanten) • ausgehend von Startknoten s • kürzeste Pfade selbst erfordern Modifikation des Algorithmus 40 Zusammenfassung Notizen 7 Fortgeschrittene Datenstrukturen 8 Such-Algorithmen 9 Graph-Algorithmen Tiefensuche Breitensuche 41 Notizen