Algorithmen und Datenstrukturen (für ET/IT)

Werbung
Notizen
Algorithmen und Datenstrukturen (für ET/IT)
Wintersemester 2012/13
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
Kürzeste Pfade
3
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
4
Segmentierung von Bildern
Notizen
• Segmentierung: Zusammenfassung von inhaltlich
zusammenhängenden Regionen gemäß eines Kriteriums
• Beispiel: Segmentierung von Knochen oder Organen
5
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?
6
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
7
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
8
“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)
9
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)
10
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)
11
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;
12
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
13
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
14
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
15
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)
16
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)
17
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
18
Programm heute
Notizen
7 Fortgeschrittene Datenstrukturen
8 Such-Algorithmen
9 Graph-Algorithmen
Tiefensuche
Breitensuche
Kürzeste Pfade
19
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
20
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
21
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)
22
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
23
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
}
24
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
25
BFS: Beispiel-Ablauf 2
r
s
∞
t
u
0
r
∞
∞
∞
w
r
s
1
∞
x
1
∞
∞
u
∞
v
1
w
r
s
1
2
x
r
2
2
r
x
v
∞
2
1
v
Q:
v
u
y
3
2
w
v
u
2
u
y
x
y
t
0
t
∞
x
s
1
Q:
∞
2
w
3
2
x
1
v
r
u
2
x
u
2
1
w
t
∞
Q:
v
r
w
y
t
0
Q:
∞
x
s
1
y
t
0
∞
∞
w
∞
Q:
u
∞
1
v
2
t
0
s
y
t
0
s
∞
Q:
v
Notizen
3
x
y
26
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
27
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
28
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 |)
29
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
30
Programm heute
Notizen
7 Fortgeschrittene Datenstrukturen
8 Such-Algorithmen
9 Graph-Algorithmen
Tiefensuche
Breitensuche
Kürzeste Pfade
31
Definition Kürzester Pfad
Notizen
Sei G = (V , E ) Graph mit Gewichtsfunktion
w : E → R.
• das Gewicht eines Pfades p = (v1 , . . . , vk ), vi ∈ V ,
i = 1, . . . , k, ist die Summe der Gewichte aller seiner Kanten
w (p) =
k−1
X
w (vi , vi+1 )
i=1
• das Gewicht des kürzesten Pfades zwischen zwei Knoten u
und v (u, v ∈ V ) ist
(
min{w (p) : p Pfad von u nach v } Pfad existiert
wmin (u, v ) =
∞
sonst
32
Beispiel: kürzeste Pfade
Notizen
Navigationssystem:
HH
• Knoten sind Großstädte
H
• Gewichte der Kanten sind (grobe)
200
350
450
DD
200
300
F
200
Fragestellungen:
anderen Städten?
200
K
Entfernungen in Kilometern
• alle kürzesten Verbindungen von M zu
B
250
300
• Kanten sind Autobahnverbindung
• kürzester Weg von M nach HH?
200
300
150
KA
N
50
S
250
150
M
• alle kürzesten Verbindungen zwischen
allen Städten?
33
Kürzeste Pfade: Algorithmen
Notizen
Sei G = (V , E ) gewichteter, gerichteter Graph.
• Kürzeste Pfade in Graphen von fixem Startknoten s:
• Dijkstra-Algorithmus (nur positive Kantengewichte)
Greedy-Algorithmus
Komplexität: O(|E | log |V |)
• A*-Algorithmus (nur positive Kantengewichte)
Komplexität: mit guter Heuristik, besser als Dijkstra
• Bellman-Ford-Algorithmus (auch negative Gewichte)
Komplexität: O(|V | ∗ |E |)
• Kürzeste Pfade in Graphen zwischen allen Knotenpaaren:
• Floyd-Warshall-Algorithmus (all pairs shortest path)
basiert auf dynamischer Programmierung
Komplexität: Θ(|V |3 )
34
Gegenbeispiel Greedy-Algorithmus
Notizen
2
1
1
10
4
4
5
9
3
• Greedy-Schema: füge kürzeste Kante zu Pfad (so dass kein
Zyklus entsteht)
•
•
•
•
Starte bei Knoten 1
füge Kante (1,2) hinzu (Kosten 1)
füge Kante (2,3) hinzu (Kosten 4)
füge Kante (3,4) hinzu (Kosten 9)
• Problem: Pfad von 1 nach 4 hat Kosten 14, kürzester Pfad
hat aber Kosten 11!
35
Beispiel: Ablauf Dijkstra-Algorithmus 1
80
1
60
4
60
120
5
Länge
0
100
20
3
Kürzester Pfad
5
2
40
Notizen
120
6
40
Knoten
hinzugefügt
1
3
6
Pfad
Pfad Länge
5
5
5
60
120
40
36
Beispiel: Ablauf Dijkstra-Algorithmus 2
80
1
2
40
60
100
20
3
5
40
Kürzester Pfad
5
5,6
Länge
0
40
4
60
120
Notizen
120
6
Knoten
hinzugefügt
1
3
4
Pfad
Pfad Länge
5
5,6
5,6
60
100
160
37
Beispiel: Ablauf Dijkstra-Algorithmus 3
80
1
2
40
60
100
20
3
5
Kürzester Pfad
5
5,6
5,1
Länge
0
40
60
4
60
120
Notizen
120
6
40
Knoten
hinzugefügt
2
3
4
Pfad
Pfad Länge
5,1
5,6
5,6
140
100
160
38
Beispiel: Ablauf Dijkstra-Algorithmus 4
80
1
2
40
60
100
20
3
60
120
5
4
40
Notizen
Kürzester Pfad
5
5,6
5,1
5,6,3
Länge
0
40
60
100
120
6
Knoten
hinzugefügt
2
4
Pfad
Pfad Länge
5,1
5,6,3
140
120
39
Beispiel: Ablauf Dijkstra-Algorithmus 5
80
1
2
40
60
100
20
3
60
120
5
4
120
6
40
Notizen
Kürzester Pfad
5
5,6
5,1
5,6,3
5,6,3,4
Knoten
hinzugefügt
2
Länge
0
40
60
100
120
Pfad
Pfad Länge
5,1
140
40
Beispiel: Ablauf Dijkstra-Algorithmus 6
80
1
2
40
60
100
20
3
60
120
5
4
40
120
Notizen
Kürzester Pfad
5
5,6
5,1
5,6,3
5,6,3,4
5,1,2
Länge
0
40
60
100
120
140
6
fertig
41
Dijkstra-Algorithmus
Notizen
Sei G = (V , E ) Graph mit Gewicht w : E → R+ (positive reelle
Zahlen).
• Startknoten s ∈ V für kürzesten Pfad
• Graph repräsentiert mit Adjazenzliste adj
• jeder Knoten (ausser s) hat Vorgänger im kürzesten Pfad pred
• jeder Knoten hat Markierung d
• Distanz (bzgl. Gewicht) von Startknoten s
• Hilfsmittel: Priority Queue Q
42
Algorithmus: Dijkstra
Notizen
Input: Graph G = (V , E ), w : E → R+ , Startknoten s ∈ V
Output: Vorgänger-Liste pred, Distanz-Markierung d
Dijkstra(G , w , s):
for each (Knoten v ∈ V ) { // Initialisierung
pred[v ] = NULL; d[v ] = ∞;
}
d[s] = 0;
Q = Priority Queue mit Elementen V , Schlüsseln d;
while ( !Q.isEmpty() ) {
u = Q.extractMin();
for each (v ∈ adj[u] mit v ∈ Q) {
if (d[u] + w (u, v ) < d[v ]) {
pred[v ] = u; d[v ] = d[u] + w (u, v );
Q.decreaseKey(v , d[v ]);
}
}
}
43
Beispiel: Ablauf Dijkstra-Algorithmus 1
u
1
∞
v
∞
2 3
0
5 6
s
∞
∞
5
y
1
8
(x, 5) (u, 10) (v, ∞)
v
u
∞
y
(y, ∞)
1
8
10
∞
2
x
Q:
(u, ∞) (v, ∞) (x, ∞) (y, ∞)
u
5 6
7
5
2
x
v
13
10
s
2 3
0
5 6
s
5
(u, 8)
5 6
7
5
7
2
x
2 3
0
7
5
(y, 7)
∞
2 3
0
7
5
Q:
v
10
s
(s,0)
1
10
10
Q:
Notizen
u
5
y
Q:
(v, ∞)
7
2
x
y
(u, 8) (v, 13)
44
Beispiel: Ablauf Dijkstra-Algorithmus 2
u
1
8
v
13
1
8
10
v
9
10
s
2 3
0
5 6
s
5
5
y
x
Q:
(u, 8) (v, 13)
u
1
8
5 6
7
5
7
2
x
2 3
0
7
5
Q:
Notizen
u
2
7
y
(v, 9)
v
9
10
s
2 3
0
5 6
7
5
5
x
2
7
y
Q:
45
Zusammenfassung
Notizen
7 Fortgeschrittene Datenstrukturen
8 Such-Algorithmen
9 Graph-Algorithmen
Tiefensuche
Breitensuche
Kürzeste Pfade
46
Notizen
Zugehörige Unterlagen
Herunterladen