Algorithmen und Datenstrukturen (für ET/IT - CAMP-TUM

Werbung
Algorithmen und Datenstrukturen (für ET/IT)
Wintersemester 2012/13
Dr. Tobias Lasser
Computer Aided Medical Procedures
Technische Universität München
Wiederholung Graph-Algorithmen
Algorithmus DFS
Input: Graph G = (V , E )
Output: Vorgänger-Liste pred,
Markierungen d, f
DFS(G ):
for each (Knoten v 2 V ) {
farbe[v ] = weiss;
pred[v ] = NULL;
}
zeit = 0;
for each (Knoten v 2 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 2 adj[v ]) {
if (farbe[u] == weiss) {
pred[u] = v;
DFSvisit(u);
}
}
farbe[v ] = schwarz; // v ist fertig
zeit = zeit + 1;
f[v ] = zeit;
12
2
Wiederholung Graph-Algorithmen
DFS: Beispiel-Ablauf 2
u
v
w
u
1/_
Algorithmus DFSx
u
v
1/_
w
u
2/_
v
1/_
w
2/_
3/_
y
z
x
y
z
x
y
v
w
u
v
w
u
v
2/_
Input: Graph G = (V , 1/_
E)
Output: Vorgänger-Liste pred,
Markierungen4/_d, f 3/_
x
y
DFS(G ):
for each (Knoten uv 2 V )v {
2/_
farbe[v ] = weiss; 1/_
pred[v ] = NULL; B
}
4/5
3/6
x
y
zeit = 0;
for each (Knoten v 2 V ) {
if (farbe[v ] == weiss)
DFSvisit(v );
}
z
w
z
1/_
1/_
DFSvisit(v
): 2/_
B
farbe[v ] =
grau; // v war weiss B
zeit =4/_zeit +3/_ 1;
4/5
x
y
z
x
d[v ] = zeit;
for ueach (Knoten
v
w u 2 adj[v ])
u {
1/_
2/7 == weiss) {
1/_
if (farbe[u]
B
B
pred[u]
= v;
F
DFSvisit(u);
4/5
3/6
4/5
x
y
z
x
}
}
farbe[v ] = schwarz; // v ist fertig
zeit = zeit + 1;
f[v ] = zeit;
z
w
2/_
3/_
y
z
v
w
2/7
3/6
y
z
14
12
2
Wiederholung Graph-Algorithmen
Algorithmus BFS
Input: Graph G = (V , E ), Startknoten s 2 V
Output: Vorgänger-Liste pred, Markierung d
BFS(G , s):
for each (Knoten v 2 V ) { // Initialisierung
farbe[v ] = weiss; pred[v ] = NULL; d[v ] = 1;
DFS: Beispiel-Ablauf
2
}
farbe[s] = grau; d[s] = 0;
Q = initialize();
Q.enqueue(s);
u
v
w
u
v
w
u
v
w
while ( 1/_
!Q.isEmpty()
){
1/_
2/_
1/_
2/_
u = Q.dequeue();
for each (v 2 adj[u]) { // besuche alle Nachbarn
3/_
Algorithmus DFSx
ifx (farbe[v
] == zweiss) { x
y
z
y
y
z
farbe[v ] = grau; d[v ] = d[u] + 1; pred[v ] = u;
);w
u
v
w
u Q.enqueue(v
v
u
v
w
2/_
1/_
2/_
} 1/_ ): 2/_
Input: Graph G = (V , 1/_
E)
DFSvisit(v
B
}
Output: Vorgänger-Liste pred,
farbe[v
]=
grau; // v war weiss B
farbe[u] = schwarz; // u ist erledigt
Markierungen4/_d, f 3/_
zeit
=4/_zeit +3/_ 1;
4/5
3/_
}
x
y
z
x
y
z
x
y
z
DFS(G ):
for each (Knoten uv 2 V )v {
2/_
farbe[v ] = weiss; 1/_
pred[v ] = NULL; B
}
4/5
3/6
x
y
zeit = 0;
for each (Knoten v 2 V ) {
if (farbe[v ] == weiss)
DFSvisit(v );
}
w
z
d[v ] = zeit;
for ueach (Knoten
v
w u 2 adj[v ])
u {
1/_
2/7 == weiss) {
1/_
if (farbe[u]
B
B
pred[u]
= v;
F
DFSvisit(u);
4/5
3/6
4/5
x
y
z
x
}
}
farbe[v ] = schwarz; // v ist fertig
zeit = zeit + 1;
f[v ] = zeit;
v
w
24
2/7
3/6
y
z
14
12
2
Wiederholung Graph-Algorithmen
Algorithmus BFS
Input: Graph G = (V , E ), Startknoten s 2 V
Output: Vorgänger-Liste pred, Markierung d
BFS(G , s):
for each (Knoten v 2 V ) { // Initialisierung
farbe[v ] = weiss; pred[v ] = NULL; d[v ] = 1;
DFS: Beispiel-Ablauf
2 BFS: Beispiel-Ablauf 2
}
farbe[s] = grau; d[s] = 0;
Q = initialize();
Q.enqueue(s);
u
v
w
u
v
w
u
v
w
while ( 1/_
!Q.isEmpty()
1/_
1/_
2/_
r2/_
s) {
t
u
r
∞
0
∞
∞
u = Q.dequeue();
Q: Nachbarn
s
for each (v 2 adj[u]) { // besuche alle
Algorithmus DFSx
ifx (farbe[v
] ==
weiss) { ∞ x ∞ y 3/_
∞
y
z
y
z ∞
z
w
farbe[v ]v = grau;
d[v ]x = d[u]y + 1; pred[v ] = u; v
);w
u
v
w
u Q.enqueue(v
v
u
v
w
r
s
t
u
r
2/_
1/_ ∞
2/_
} 1/_ ): 2/_1
0
2
Input: Graph G = (V , 1/_
E)
DFSvisit(v
B
}
Output: Vorgänger-Liste pred,
farbe[v
]=
grau; // v war weiss B Q: r t x
farbe[u] = schwarz;
u ist2 erledigt
1
Markierungen4/_d, f 3/_
zeit
=4/_zeit +v3/_∞1; w //
4/5 ∞
3/_
x
v
}
x
y
z
x
y
z
x y
y
z
DFS(G ):
for each (Knoten uv 2 V )v {
2/_
farbe[v ] = weiss; 1/_
pred[v ] = NULL; B
}
4/5
3/6
x
y
zeit = 0;
for each (Knoten v 2 V ) {
if (farbe[v ] == weiss)
DFSvisit(v );
}
w
z
d[v ] = zeit;
t
for ueach (Knoten
])
v r
wsu 2 adj[v
u u{
1
0
2
3
1/_
2/7 == weiss) {
1/_
if (farbe[u]
B
B
pred[u]
= v;
F
2
1
2
∞
v
w
x
y
DFSvisit(u);
4/5
3/6
4/5
x
y
z
x
}
}
farbe[v ] = schwarz; // v ist fertig
zeit = zeit + 1;
f[v ] = zeit;
v
Q:
v
u
∞
∞
1
∞
w
x
s
1
2
2
v
u
2
1
w
2
x
Q:
t
x
v
Q:
v
u
y
∞
y
t
0
r
∞
2
x
s
1
w
u
2
1
w
Q:
∞
y
t
0
∞
243
u
3/6
y
t
0
r
w
2/7
x
s
1
3
y
z
14
26
12
2
Programm heute
7 Fortgeschrittene Datenstrukturen
8 Such-Algorithmen
9 Graph-Algorithmen
Tiefensuche
Breitensuche
Kürzeste Pfade
Minimaler Spannbaum
10 Numerische Algorithmen
Matrizen
3
Wiederholung Kürzeste Pfade
Beispiel: kürzeste Pfade
Navigationssystem:
HH
• Knoten sind Großstädte
• Kanten sind Autobahnverbindung
200
450
DD
200
300
F
200
Fragestellungen:
anderen Städten?
200
350
K
Entfernungen in Kilometern
• alle kürzesten Verbindungen von M zu
B
H
• Gewichte der Kanten sind (grobe)
• kürzester Weg von M nach HH?
200
250
300
300
150
KA
N
50
S
250
150
M
• alle kürzesten Verbindungen zwischen
allen Städten?
33
4
Wiederholung Kürzeste Pfade
Kürzeste Pfade: Algorithmen
Sei G = (V , E ) gewichteter, gerichteter Graph.
• Kürzeste Pfade in Graphen von fixem Startknoten s:
• Dijkstra-Algorithmus (nur positive Kantengewichte)
Beispiel: kürzeste PfadeGreedy-Algorithmus
Komplexität: O(|E | log |V |)
Navigationssystem:
• A*-Algorithmus (nur positive Kantengewichte)
Komplexität: mit guter Heuristik,
besser
als Dijkstra
HH
200
Gewichte)
• Knoten sind Großstädte• Bellman-Ford-Algorithmus (auch negative
B
250
300
Komplexität: O(|V | ⇤ |E |) H
• Kanten sind Autobahnverbindung
200
350
450 Knotenpaaren:
• Kürzeste
• Gewichte der Kanten
Pfade in Graphen 200
zwischen
allen
sind (grobe)
K
DD
• Floyd-Warshall-Algorithmus (all pairs shortest path)
Entfernungen in Kilometern
200
F
300
basiert auf dynamischer
Programmierung
200
300
150
Fragestellungen:
Komplexität: ⇥(|V |3 )
N
50
KA
• kürzester Weg von M nach HH?
S
• alle kürzesten Verbindungen von M zu
anderen Städten?
250
150
M
34
• alle kürzesten Verbindungen zwischen
allen Städten?
33
4
Wiederholung Kürzeste Pfade
Beispiel: Ablauf Dijkstra-Algorithmus 1
u
v
1
∞
u
∞
2 3
0
s
5 6
∞
5
y
(x, 5) (u, 10) (v, ∞)
• Dijkstra-Algorithmusu(nur positivev Kantengewichte)
1
8
2 3
s
5 6
0 (nur positive Kantengewichte)
• A*-Algorithmus
Q:
(y, 7)
(u, 8)
(auch
2
2 3
0
7
Komplexität: mit5guter Heuristik,
besser
als Dijkstra
HH
200
Komplexität: O(|V | ⇤ |E |)
• Kanten sind Autobahnverbindung
1
8
v
13
10
Komplexität: O(|E | log |V |)
5
Bellman-Ford-Algorithmus
x
300
y
(y, ∞)
u
∞
10
∞
2
x
Q:
Q:
(s,0) (u, ∞)
(v, ∞) (x, ∞) Graph.
(y, ∞)
Sei G = (V , E ) gewichteter,
gerichteter
• Kürzeste Pfade in Graphen von fixem Startknoten s:
Beispiel: kürzeste PfadeGreedy-Algorithmus
5 6
7
5
2
x
• Knoten sind Großstädte•
∞
2 3
0
7
5
Kürzeste Pfade: Algorithmen
∞
Navigationssystem:
v
10
s
s
1
10
10
H
200
(v, ∞)
Q:
7
5
7
negative
Gewichte)
B
250 y
5 6
5
x
2
7
y
(u, 8) (v, 13)
450 Knotenpaaren:
• Kürzeste
• Gewichte der Kanten
Pfade in Graphen 200
zwischen allen
sind (grobe)
K
DD
• Floyd-Warshall-Algorithmus (all pairs shortest path)
Entfernungen in Kilometern
200
F
300
basiert auf dynamischer
Programmierung
200
300
150
Fragestellungen:
Komplexität: ⇥(|V |3 )
N
50
KA
• kürzester Weg von M nach HH?
350
S
• alle kürzesten Verbindungen von M zu
anderen Städten?
250
44
150
M
34
• alle kürzesten Verbindungen zwischen
allen Städten?
33
4
Wiederholung Kürzeste Pfade
Beispiel: Ablauf Dijkstra-Algorithmus 1
u
1
∞
v
u
∞
s
0
v
∞
10
2 3
s
5 6
x
2
2 3
0
7
5
Kürzeste Pfade: Algorithmen
Dijkstra-Algorithmus
∞
∞
Beispiel:
1
10
10
y
5 6
7
5
5
x
2
∞
y
Q:
Q: (x, 5) (u, 10) (v, ∞) (y, ∞)
(s,0) (u, ∞)
(v, ∞) (x, ∞) Graph.
(y, ∞)
Sei G = (V , E ) gewichteter,
gerichteter
• Kürzeste Pfade in Graphen von fixem Startknoten s:
G =v Kantengewichte)
(V , E ) Graph mit Gewicht
w :E !
R+ (positive reelle
• Dijkstra-Algorithmusu(nurSei
positive
u
v
1
1
∞
8
13
kürzeste PfadeGreedy-Algorithmus 8 Zahlen).
10
10
Komplexität: O(|E
| log |V |) • Startknoten s 2 V für kürzesten
Pfad
s
s
2 3
5 6
0 (nur positive Kantengewichte)
• A*-Algorithmus
• Graph repräsentiert
2 3
5 6
0
mit
Adjazenzliste adj
7
7
Komplexität: mit5guter Heuristik,
besser als Dijkstra
• HHjeder200Knoten (ausser s)5hat Vorgänger im kürzesten Pfad pred
5
7
5
7
(auch
negative
Gewichte)
2
• Knoten sind Großstädte• Bellman-Ford-Algorithmus
B
250
• jeder Knoten
hat Markierung dx 2
x
y
y
300
Komplexität: O(|V | ⇤ |E |) H
• Kanten sind Autobahnverbindung
• Distanz (bzgl.
Gewicht) von Startknoten s
200
Q: (y, 7) (u, 8) (v, ∞)
Q: (u, 8) (v, 13)
350
450 Knotenpaaren:
• Kürzeste
• Gewichte der Kanten
Pfade in Graphen 200
zwischen
allen
sind (grobe)
• Hilfsmittel:
Priority Queue Q
44
K
DD
• Floyd-Warshall-Algorithmus (all pairs shortest path)
Entfernungen in Kilometern
200
F
300
basiert auf dynamischer
Programmierung
200
300
150
Fragestellungen:
Komplexität: ⇥(|V |3 )
N
50
KA
• kürzester Weg von M nach HH?
Navigationssystem:
S
• alle kürzesten Verbindungen von M zu
anderen Städten?
250
150
M
34
42
• alle kürzesten Verbindungen zwischen
allen Städten?
33
4
Algorithmus: Dijkstra
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() ) { // Hauptschleife
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 ]);
}
}
}
5
Dijkstra-Algorithmus
Nach Ausführung von Dijkstra(G , w , s) gilt für v ∈ V :
• d[v ] = Gewicht wmin (v , s) des kürzesten Pfades von v zu s
• pred[v ] = Vorgängerknoten
• Kürzester Pfad von v zu s:
pred[v ], pred[pred[v ]], . . . , s
Beispiel:
u
1
8
v
9
10
s
2 3
0
5 6
7
5
5
x
2
7
y
6
Dijkstra: Laufzeit
Laufzeit:
• Annahme: Q implementiert als
binärer Min-Heap
• Zeile 1-3: O(|V |)
• Zeile 5: entspricht buildMinHeap,
also O(|V |)
• Zeile 6-15: Ausführung |V | mal
• Zeile 7: O(log |V |)
• Zeile 8-14: Ausführung inkl.
äusserer while-Schleife:
insgesamt |E | mal (siehe
DFS/BFS)
• Zeile 12: O(log |V |)
Dijkstra(G , w , s):
1
for each (Knoten v ∈ V ) {
2
pred[v ] = NULL; d[v ] = ∞;
3
}
4
d[s] = 0;
5
Q = Priority Queue(V , d);
6
while ( !Q.isEmpty() ) {
7
u = Q.extractMin();
8
for each (v ∈ adj[u] mit v ∈ Q) {
9
if (d[u] + w (u, v ) < d[v ]) {
10
pred[v ] = u;
11
d[v ] = d[u] + w (u, v );
12
Q.decreaseKey(v , d[v ]);
13
}
14
}
15 }
Gesamt: O (|V | + |E |) log |V |
einfacher: O(|E | log |V |)
7
Dijkstra: Komplexität
• Komplexität des Dijkstra Algorithmus hängt entscheidend von
der Implementierung der Priority Queue ab!
• Varianten:
• als verkettete Liste: O(|V |2 )
• als binärer Heap: O(|E | log |V |)
• als Fibonacci Heap: O(|E | + |V | log |V |)
8
Dijkstra: Korrektheit
(nur Beweisidee, dies ist kein formaler Beweis!)
Annahme: bisherige Iterationen waren korrekt, bisher bearbeitete
Knoten: X ⊂ V
• nächster Iterationsschritt nimmt kürzeste direkte Verbindung
von Knoten x ∈ X zu noch nicht bearbeitetem Knoten
y ∈ V \ X hinzu
• d[y ] ist nun d[x] + w (x, y )
• jeder andere Pfad zu y hat entweder
• eine Kante, die aus X heraus geht und ist damit nicht kürzer
als (x, y )
• mehrere Kanten, und ist damit nicht kürzer als d[y ], da die
Kanten positives Gewicht haben
Entscheidende Annahme: Kanten haben positives Gewicht!
9
Dijkstra: Anwendungen
Dijkstra ist einer der am häufigsten verwendete Graph-Algorithmen
Beispiele:
• Routenplanung in GIS (Geographic Information System)
• Navigationssystem im Auto
• Maps Applikation (Google, Bing, Apple etc.)
• Routen mit Flugzeugen, Bahn usw.
• Routing Protokolle für IP Netzwerke
• z.B. Open Shortest Path First
• Pfadplanung von Robotern, UAV/Dronen, etc.
• Segmentierung von medizinischen Bilddaten
10
Programm heute
7 Fortgeschrittene Datenstrukturen
8 Such-Algorithmen
9 Graph-Algorithmen
Tiefensuche
Breitensuche
Kürzeste Pfade
Minimaler Spannbaum
10 Numerische Algorithmen
Matrizen
11
Minimaler Spannbaum
Sei G = (V , E ) zusammenhängender Graph mit Gewichtsfunktion
w : E → R.
• Spannbaum: Teilgraph G 0 = (V , E 0 ), der ein Baum ist und
alle Knoten von G enthält.
• minimaler Spannbaum: Spannbaum G 0 mit minimalem
Gewicht
wG 0 =
X
w (x, y )
(x,y )∈E
12
Minimaler Spannbaum: Beispiel
Beispiel: 6 (virtuelle) Städte und Kosten für Strassenbau
dazwischen (in Million Euro):
Awl
Dresh
4
0
0
5
2
Rennis
3
0
6
3
2
0
Sadon
0
1
Brous
6
0
Gedry
Problem: Strassenbau mit minimalen Kosten, so daß alle Städte
verbunden sind (direkt oder über andere Städte)
Lösung: minimaler Spannbaum
13
Minimaler Spannbaum: Beispiel 2
Mögliche Lösungen:
Awl
Dresh
4
0
Awl
0
5
0
1
Dresh
0
2
Rennis
0
4
0
Rennis
3
0
Brous
1
0
Brous
6
2
0
Sadon
Gewicht: 18
0
2
0
Gedry
Sadon
0
Gedry
Gewicht: 12
14
Minimaler Spannbaum: Algorithmen
Sei G = (V , E ) zusammenhängender Graph mit Gewichtsfunktion
w : E → R.
• Minimaler Spannbaum von G :
• Algorithmus von Kruskal: Greedy-Algorithmus
Komplexität: O(|E | log |V |)
• Algorithmus von Prim: Greedy-Algorithmus
Komplexität: O(|E | log |V |)
• viele Varianten davon als parallele Algorithmen
15
Beispiel-Ablauf: Prim Algorithmus 1
4
1
2
5
2
3
3
6
3
2
5
6
5
4
2
5
2
3
6
6
6
6
1
4
1
3
2
2
5
3
6
3
2
4
1
6
2
5
3
5
4
1
3
3
6
2
2
4
1
4
1
3
6
5
3
2
4
1
6
6
16
Beispiel-Ablauf: Prim Algorithmus 2
4
1
2
5
2
3
3
6
3
2
5
6
5
4
2
5
2
3
6
6
6
6
1
4
1
3
2
2
5
3
6
3
2
4
1
6
2
5
3
5
4
1
3
3
6
2
2
4
1
4
1
3
6
5
3
2
4
1
6
6
17
Beispiel-Ablauf: Prim Algorithmus 3
4
1
2
5
2
3
3
6
5
3
2
3
6
6
2
5
2
4
1
4
1
3
6
5
3
2
4
1
6
6
Beobachtungen:
• Zwischenlösungen von Prim Algorithmus sind Bäume
• es werden öfters mehrere Kanten zum selben Knoten
betrachtet (s. oben)
• Vereinfachung: betrachte nur Kante mit minimalem Gewicht
18
Prim Algorithmus
Sei G = (V , E ) zusammenhängender Graph mit Gewichtsfunktion
w : E → R.
• Startknoten s ∈ V für minimalen Spannbaum
• Graph repräsentiert als Adjazenzliste adj
• jeder Knoten (ausser s) hat Vorgänger im Spannbaum pred
• jeder Knoten hat Markierung g
• kleinstes Gewicht um Knoten mit aktuellem Spannbaum zu
verbinden
• Hilfsmittel: Priority Queue Q
19
Algorithmus: Prim
Input: Graph G = (V , E ), w : E → R, Startknoten s ∈ V
Output: Vorgänger-Liste pred
Prim(G , w , s):
for each (Knoten v ∈ V ) { // Initialisierung
pred[v ] = NULL; g[v ] = ∞;
}
g[s] = 0;
Q = Priority Queue mit Elementen V , Schlüsseln g;
while ( !Q.isEmpty() ) { // Hauptschleife
u = Q.extractMin();
for each (v ∈ adj[u] mit v ∈ Q) {
if (w (u, v ) < g[v ]) {
pred[v ] = u; g[v ] = w (u, v );
Q.decreaseKey(v , g[v ]);
}
}
}
20
Beispiel: Ablauf Prim Algorithmus 1
u
v
8
∞
4
u
∞
4
2
s
r
0
11
7
8
(s,0)
y
4
u
7
8
8
x
y
Q: (v, 8) (x, 8) (r, ∞) (y, ∞) (z, ∞)
2
8
r
0
11
∞
8
z
x
Q: (r, 2)
(z, 4)
4
2
7
8
∞
∞
z
2
s
4
6
1
2
v
8
4
4
∞
y
Q: (u, 4) (x, 8) (r, ∞) (v, ∞) (y, ∞) (z, ∞)
8
r
11
∞
1
x
2
s
6
8
z
4
∞
7
∞
v
8
4
0
2
(u, ∞) (v, ∞) (r, ∞) (x, ∞) (y, ∞) (z, ∞)
u
11
8
∞
1
x
Q:
r
0
6
∞
∞
2
s
4
∞
v
8
4
6
1
∞
y
2
4
z
(x, 8) (y, ∞)
21
Beispiel: Ablauf Prim Algorithmus 2
u
v
8
4
4
u
8
4
2
s
r
0
11
7
8
(z, 4)
y
4
u
8
8
7
x
Q:
(y, 2) (x, 7)
4
z
y
r
0
11
2
4
1
z
x
4
2
7
8
2
8
2
s
4
6
1
2
v
8
4
4
2
7
y
Q: (z, 4) (x, 7) (y, 6)
r
11
6
1
x
2
s
6
7
z
4
2
7
4
v
8
4
0
2
(x, 8) (y, ∞)
u
11
8
∞
1
x
Q: (r, 2)
r
0
6
8
8
2
s
4
2
v
8
4
6
1
2
y
2
4
z
Q: (x, 1)
22
Beispiel: Ablauf Prim Algorithmus 3
u
v
8
4
4
u
8
4
2
s
r
0
11
7
8
1
x
Q: (x, 1)
r
0
6
1
y
11
2
4
1
z
4
2
7
8
2
8
2
s
4
2
v
8
4
x
6
1
2
y
2
4
z
Q:
Nach Ausführung von Prim(G , w , s) gilt für v ∈ V :
• pred[v ] = Vorgängerknoten im Spannbaum
• Pfad in Spannbaum von v zu Wurzel s:
pred[v ], pred[pred[v ]], . . . , s
23
Prim: Laufzeit
Laufzeit:
• Annahme: Q implementiert als
binärer Min-Heap
• Zeile 1-3: O(|V |)
• Zeile 5: entspricht buildMinHeap,
also O(|V |)
• Zeile 6-14: Ausführung |V | mal
• Zeile 7: O(log |V |)
• Zeile 8-13: Ausführung inkl.
äusserer while-Schleife:
insgesamt |E | mal (siehe
DFS/BFS)
• Zeile 11: O(log |V |)
Prim(G , w , s):
1
for each (Knoten v ∈ V ) {
2
pred[v ] = NULL; g[v ] = ∞;
3
}
4
g[s] = 0;
5
Q = Priority Queue(V , g);
6
while ( !Q.isEmpty() ) {
7
u = Q.extractMin();
8
for each (v ∈ adj[u] mit v ∈ Q) {
9
if (w (u, v ) < g[v ]) {
10
pred[v ] = u; g[v ] = w (u, v );
11
Q.decreaseKey(v , g[v ]);
12
}
13
}
14 }
Gesamt: O (|V | + |E |) log |V |
einfacher: O(|E | log |V |)
24
Prim: Komplexität
• Komplexitätsanalyse von Prim fast identisch mit Dijkstra!
• Komplexität des Algorithmus von Prim hängt entscheidend
von der Implementierung der Priority Queue ab!
• Varianten:
• als verkettete Liste: O(|V |2 )
• als binärer Heap: O(|E | log |V |)
• als Fibonacci Heap: O(|E | + |V | log |V |)
25
Prim: Anwendungen
• Planung von Netzwerken
• Strassennetz
• Kommunikations-Netzwerk
• elektronische Schaltungen
• Clustering von Daten
• Daten als Knoten, “Nähe” als Kanten, entferne “lange”
Kanten aus minimalem Spannbaum → Clustering
• Extrahieren/Tracking von Objekten aus Bildern in Computer
Vision
26
Ausblick: Graphen-Algorithmen
• Fluss in Graphen: statt Kantengewichten gibt es Kapazitäten,
betrachtet wird Fluss von Quelle zu Senke
• Problem: finde maximalen Fluss
• Anwendung: z.B. Fluss in Kommunikations-Netzwerken
• Einfärben von Graphen: Färbe Knoten von Graph so ein, dass
keine benachbarten Knoten diesselbe Farbe haben
• Anwendungen: z.B. Scheduling, Sudoku
• Planare Graphen: lässt sich Graph ohne
Kanten-Überschneidung zeichnen?
• Anwendung: z.B. Chip- bzw. Platinen-Design
• Klassifikation von medizinischen Daten: über analytische
Operationen auf Adjazenzmatrix, z.B. Laplace-Operator
• Anwendungen: z.B. Identifikation von Melanomen, Tracking
von Endoskopen
27
Programm heute
7 Fortgeschrittene Datenstrukturen
8 Such-Algorithmen
9 Graph-Algorithmen
Tiefensuche
Breitensuche
Kürzeste Pfade
Minimaler Spannbaum
10 Numerische Algorithmen
Matrizen
28
What is the matrix?
Was ist eine Matrix?
• Anordnung von Zahlen (aji ) ⊂ R in einem m × n Muster:

a11
 ..
 .
am1

· · · a1n
..  =: A
..
.
. 
· · · amn
• Element des Vektorraumes Rm×n
A ∈ Rm×n
• Lineare Abbildung f : Rn → Rm mit
f (x) = Ax
wobei A m × n Matrix.
29
Beispiel: Anwendung von Matrizen
• Adjazenzmatrix von Graphen
• effizienter als Adjazenzlisten für dichte Graphen (viele Kanten)
• erlaubt analytische Operationen wie
Laplace-Operator/Eigenwerte
• Bilder im Computer: gespeichert als Matrix
30
Speicherung von Matrizen
Speicherung als sequentielle Liste / Array:
• row-major: Zeilen werden zuerst durchlaufen


a11 a12 a13
a21 a22 a23 
a31 a32 a33
⇒
[a11 , a12 , a13 , a21 , a22 , a23 , a31 , a32 , a33 ]
• column-major: Spalten werden zuerst durchlaufen


a11 a12 a13
a21 a22 a23 
a31 a32 a33
⇒
[a11 , a21 , a31 , a12 , a22 , a32 , a13 , a23 , a33 ]
31
Matrix-Operationen
Seien A, B ∈ Rm×n mit A = (aji ), B = (bji ) und λ ∈ R.
• Addition:


a11 + b11 · · · a1n + b1n


..
..
..
A+B =

.
.
.
am1 + bm1 · · · amn + bmn
• Skalarmultiplikation:

λa11
 ..
λA =  .
λam1

· · · λa1n
.. 
..
.
. 
· · · λamn
32
Matrix-Operationen (Fortsetzung)
Seien A = (aji ) ∈ Rm×n , x = (xi ) ∈ Rn und B = (bji ) ∈ Rn×r .
• Matrix-Vektor-Multiplikation:


a11 x1 + . . . + a1n xn


..
A·x =

.
am1 x1 + . . . + amn xn
• Matrix-Matrix-Multiplikation:


a11 b11 + . . . + a1n bn1 · · · a11 b1r + . . . + a1n bnr


..
..
..
A·B = 

.
.
.
am1 b11 + . . . + amn bn1 · · · am1 b1r + . . . + amn bnr
33
Matrix-Multiplikation
n
m
r
•
r
=
n
m
34
Matrix-Multiplikation 2
n
m
r
•
r
=
n
m
35
Matrix-Multiplikation 3
n
m
r
•
r
=
n
m
36
Matrix-Multiplikation: Komplexität
Seien A = (aji ) ∈ Rn×n und B = (bji ) ∈ Rn×n (quadratisch).


a11 b11 + . . . + a1n bn1 · · · a11 b1n + . . . + a1n bnn


..
..
..
A·B =

.
.
.
an1 b11 + . . . + ann bn1 · · · an1 b1n + . . . + ann bnn
Komplexität:
• pro Eintrag: n Additionen, n Multiplikationen
• insgesamt n2 Einträge
• A · B also n3 Additionen und n3 Multiplikationen
• Komplexität: Θ(n3 ) arithmetische Operationen
37
Beispiel: Anwendung von Matrix-Multiplikation
• Wechsel von Koordinaten-Systemen können als
Matrix-Vektor-Multiplikation dargestellt werden
• Matrix heisst hier auch Transformation
• mehrere Wechsel hintereinander können mittels
Matrix-Matrix-Multiplikation zu einer Transformation
zusammengefasst werden
Beispiel: Augmented Reality
Kamera
Transformation
Transformation
Bildschirm
Welt
38
Demo: Augmented Reality
Augmented Reality Demo
39
Matrix-Multiplikation: Strassen-Algorithmus
Seien A, B ∈ Rn×n mit n 2er-Potenz (n = 2k ), n > 1.
• Divide & Conquer Ansatz zur Matrizen-Multiplikation
• A, B aufteilen in vier n/2 × n/2 Matrizen:
a11 a12
A=
,
a21 a22
B=
b11 b12
b21 b22
• Produkt A · B berechnen als:
A·B =
a11 b11 + a12 b21 a11 b12 + a12 b22
a21 b11 + a22 b21 a21 b12 + a22 b22
• aik bkj ist selbst Matrix-Matrix-Produkt
• rekursiv aufteilen bis 1 × 1 Produkt
• Komplexität: immer noch Θ(n3 )
40
Strassen-Algorithmus
• Berechne:
q1 = (a11 + a22 ) · (b11 + b22 )
q2 = (a21 + a22 ) · b11
q3 = a11 · (b12 − b22 )
q4 = a22 · (b21 − b11 )
q5 = (a11 + a12 ) · b22
q6 = (a21 − a11 ) · (b11 + b12 )
q7 = (a12 − a22 ) · (b21 + b22 )
• Dann ist:
q1 + q4 − q5 + q7
q3 + q5
A·B =
q2 + q4
q1 + q3 − q2 + q6
• Komplexität: Θ(nlg 7 ) = Θ(n2.807 )
41
Matrix-Matrix-Multiplikation
Seien A, B ∈ Rn×n .
• naiver Algorithmus: Θ(n3 )
• Strassen-Algorithmus (1969): Θ(n2.807 )
• weniger numerisch stabil als naiver Algorithmus
• n muss 2er-Potenz sein
• benötigt deutlich mehr Speicher als naiver Algorithmus
• Coppersmith-Winograd Algorithmus (1987): O(n2.376 )
• erst praktikabel für Grössen, die mit heutigen Computern nicht
bearbeitet werden können
• es existieren verbesserte Varianten (2011) mit O(n2.3727 )
42
Zusammenfassung
7 Fortgeschrittene Datenstrukturen
8 Such-Algorithmen
9 Graph-Algorithmen
Tiefensuche
Breitensuche
Kürzeste Pfade
Minimaler Spannbaum
10 Numerische Algorithmen
Matrizen
43
Herunterladen