6 Folien/Seite - Chair 11: ALGORITHM ENGINEERING

Werbung
Motivation
Kap. 6.3: Traversieren von Graphen
Kap. 6.4: Elementare Graphalgorithmen
Heute braucht es keine Motivation,
denn:
Carsten Gutwenger
Lehrstuhl für Algorithm Engineering, LS11
Spielereien
Fakultät für Informatik, TU Dortmund
DFS
mit
18. VO
DAP2
SS
2009
25. Juni 2009
Carsten Gutwenger
DAP2 SS09
1
Carsten Gutwenger
DAP2 SS09
2
Überblick
Kap. 6.3.2 Tiefensuche
• Traversieren von Graphen:
– Breitensuche (BFS)
– Tiefensuche (DFS)
• Elementare Graphenalgorithmen:
– Zusammenhangskomponenten
– Kreise in Graphen
– Topologisches Sortieren
Carsten Gutwenger
DAP2 SS09
3
Tiefensuche (DFS)
4
Methode: DFS-VISIT(v):
• Durchlaufe alle Nachbarn von v
• Für jeden neu entdeckten (nicht markierten)
Knoten w:
– Markiere w;
– rufe DFS-VISIT(w) auf.
Idee: besuche die Knoten rekursiv: wenn v
zum ersten Mal gesehen wird, markiere ihn
als gesehen und erforsche den Graphen von
v aus weiter!
• Im Gegensatz zur Breitensuche, wird hier der
Graph erst einmal in seiner Tiefe durchdrungen.
• Bei Breitensuche werden erst alle gesehenen
Knoten bearbeitet, bevor die neuen bearbeitet
werden (Queue). Hier wir immer erst das Neue
erledigt.
DAP2 SS09
DAP2 SS09
Tiefensuche DFS
engl.: Depth-first-search, DFS
Carsten Gutwenger
Carsten Gutwenger
• Der folgende Algorithmus DFS(G) durchwandert
alle Knoten des Graphen.
• Im Feld π[w] wird jeweils der Vorgänger von w
(also v) gespeichert.
5
Carsten Gutwenger
DAP2 SS09
6
1
Algorithmus DFS(G)
Beispiel für DFS
Sei G=(V,E) ungerichteter Graph, v,w: Knoten
(1) for all v∈V do { marked[v]:=false; π[v]:=nil}
(2) for all v∈V do
(3)
if not marked[v] then DFS-VISIT(v)
2
(4) procedur DFS-VISIT(Node v)
(5)
marked[v]:=true
(6)
for all w∈N(v) do
(7)
if not marked[w] then {
(8)
π[w]:=v
(9)
DFS-VISIT(w)
(10)
}
Carsten Gutwenger
c
DAP2 SS09
7
Carsten Gutwenger
Beispiel für DFS
2
g
e
c
e
c
DAP2 SS09
2
3
3
Carsten Gutwenger
4
DAP2 SS09
10
Beispiel für DFS
f
g
e
c
4
5
Carsten Gutwenger
2
9
Beispiel für DFS
f
g
e
c
8
Beispiel für DFS
3
Carsten Gutwenger
DAP2 SS09
DAP2 SS09
11
2
3
4
5
Carsten Gutwenger
DAP2 SS09
12
2
Beispiel für DFS
2
g
e
c
3
Beispiel für DFS
4
5
Carsten Gutwenger
DAP2 SS09
2
d
e
c
6
13
2
7
3
6
b
d
e
c
4
DAP2 SS09
2
7
2
7
3
6
14
4
5
Carsten Gutwenger
DAP2 SS09
16
Beispiel für DFS
4
2
e
c
5
Carsten Gutwenger
3
6
15
Beispiel für DFS
d
e
c
DAP2 SS09
Beispiel für DFS
5
Carsten Gutwenger
4
5
Carsten Gutwenger
Beispiel für DFS
b
d
e
c
3
DAP2 SS09
17
7
3
6
4
5
Carsten Gutwenger
DAP2 SS09
18
3
Beispiel für DFS
2
c
3
4
6
7
Beispiel für DFS
2
5
Carsten Gutwenger
19
2
3
• DFS teilt die Kanten in T-Kanten und B-Kanten
• Für jede B-Kante (u,v) gilt: Es gibt genau einen Weg
von v nach u mit T-Kanten im DFS-Baum
5
7
Jeder Knoten erhält eine eindeutige DFS-Nummer.
Für die Rückwärtskanten (u,v) gilt:
DFSNUM(u) > DFSNUM(v).
•
•
DFS teilt die Kanten in T-Kanten und B-Kanten
Für jede B-Kante (u,v) gilt: Es gibt genau einen
Weg von v nach u mit T-Kanten im DFS-Baum
•
•
•
•
4
•
v
6
6
u 5
DAP2 SS09
22
Analyse von DFS
•
•
7
4
Carsten Gutwenger
DFS-Baum
3
3
v
Die orangen Kanten (diejenigen Kanten (u,v), die
zum ersten Mal v besuchen) bilden einen Baum:
den DFS-Baum (G zusammenhängend, sonst Wald)
2
20
DFS-Baum
2
Sei G
zusammenhängend
DAP2 SS09
DFS-Baum besteht aus
• Baumkanten (tree edges, T-Kanten): (π(v),v)
• Rückwärtskanten (back edges, B-Kanten): s.u.
4
6
7
5
Carsten Gutwenger
Sei G
zusammenhängend
Beispiel für DFS
4
6
7
DAP2 SS09
3
Initialisierung: Θ(|V|)
Die for-all-Schleife ohne Aufrufe von DFS-VISIT():
O(|V|).
DFS-VISIT() wird für jeden Knoten genau einmal
aufgerufen.
Jeder Aufruf von DFS-VISIT(v) (ohne Kosten der
rekursiven Aufrufe) benötigt Θ(d(v)) Zeit.
Gesamtaufwand: Θ(|V|)+∑ Θ(d(v))= Θ(|V|+|E|)
v∈V
u 5
Carsten Gutwenger
DAP2 SS09
23
Carsten Gutwenger
DAP2 SS09
24
4
BFS-Baum vs. DFS-Baum
BFS-Baum
1
2
BFS & DFS
a
3
Höhe eindeutig
1
2
2
a
b
c
c
d
e
e
3
3
f
4
g
DFS-Baum
6
7
Carsten Gutwenger
5
DAP2 SS09
BFS-Baum
25
Kap. 6.4 Elementare
Graphenalgorithmen
27
C4
T-Kanten des DFS-Waldes
Carsten Gutwenger
DAP2 SS09
DFS-Baum
Carsten Gutwenger
DAP2 SS09
26
Carsten Gutwenger
DAP2 SS09
28
Idee:
• Beginne an einem Knoten s und bestimme alle
von s aus erreichbaren Knoten →
Komponente 1 (Markierung mit 1)
• Beginne nun bei einem noch unmarkierten
Knoten v (marked==0) und bestimme alle von v
aus erreichbaren Knoten; markiere dabei mit 2
→ Komponente 2
• …u.s.w. bis alle Knoten markiert sind
C3
C2
b
Bestimmen der
Zusammenhangskomponenten
Komponenten eines Graphen
C1
g
• G heißt zusammenhängend (connected), wenn |V|≧1
und für jedes Paar u,v von Knoten ein Weg von u
nach v in G existiert.
• Ein Graph G´=(V´,E´) mit V´⊆ V und E´⊆ E ist ein
Untergraph (Teilgraph, subgraph) von G. Wir
schreiben G´⊆G.
• Eine (Zusammenhangs-) Komponente (component)
von G ist ein maximaler zusammenhängender
Untergraph U von G, d.h. es gibt keinen anderen
zusammenhängenden Untergraphen U´ mit U⊆U´.
Zusammenhangskomponenten
DAP2 SS09
d
Definitionen (Zusammenhang)
Kap. 6.4.1 Komponenten eines Graphen
Carsten Gutwenger
f
29
Carsten Gutwenger
DAP2 SS09
30
5
Algorithmus COMPONENTS(G)
Bestimmen der
Zusammenhangskomponenten
Sei G=(V,E) ungerichteter Graph, v,w: Knoten
(1) for all v∈V do { marked[v]:=0}
(2) numComps:=0
(3) for all v∈V do {
(4)
if marked[v]=0 then {
(5)
numComps:=numComps+1
(6)
DFS-COMP(v)
(7) } }
(8) Procedure DFS-COMP(Node v)
(9) marked[v]:=numComps
(10) for all w∈N(v) do
(11) if marked[w]=0 then
(12)
DFS-COMP(w)
Theorem: Der Algorithmus COMPONENTS(G)
bestimmt die Zusammenhangskomponenten
eines Graphen G=(V,E) in Zeit Θ(|V|+|E|).
Carsten Gutwenger
Kap. 6.4.2 Kreise in Graphen
DAP2 SS09
32
Kreise und DFS
• Lemma: Sei G ein ungerichteter Graph und F
ein beliebiger DFS-Wald für G. Dann ist G
genau dann kreisfrei, wenn G keine
Rückwärtskante (B-Kante) bezüglich F enthält.
• Aufgabe: Gegeben ist ein ungerichteter Graph
G=(V,E). Enthält G einen Kreis?
• Idee: mittels DFS
Beweis:
• 1. Fall: F enthält keine B-Kante: dann besteht F
nur aus T-Kanten → F enthält alle Kanten aus
G → G kreisfrei
• 2. Fall: Sei (u,v) B-Kante bzgl. F → es existiert
Weg v,…,u mit T-Kanten in F → Weg mit Kante
(u,v) bildet Kreis in G.
Carsten Gutwenger
DAP2 SS09
33
DAP2 SS09
34
Algorithmus ISACYCLIC(G)
Kreise und DFS
Sei G=(V,E) ungerichteter Graph
• Methode: Erweitere DFS um Speicherung der
B-Kanten: sobald wir von v aus auf einen
markierten Knoten u treffen, haben wir eine BKante gefunden, falls u nicht der direkte
Vorgänger (Elter) von v ist.
(1) function ISACYCLIC(Graph G=(V,E)) : bool {
(2)
B := ∅
(3)
for all v∈V do { marked[v]:=false; π(v):=nil }
(4)
for all v∈V do {
(5)
if not marked[v] then
(6)
DFS-ACYCLIC(v)
(7)
}
(8)
if B  ∅ then return false else return true
(9) }
Algorithmus ISACYCLIC(G) speichert dabei alle
B-Kanten. Wenn man nur einen Kreis finden
möchte, dann kann man abbrechen, sobald
man eine B-Kante gefunden hat.
Carsten Gutwenger
Carsten Gutwenger
DAP2 SS09
35
Carsten Gutwenger
DAP2 SS09
36
6
Algorithmus ISACYCLIC(G) ff
Welche Kreise werden gefunden?
(1) procedure DFS-ACYCLIC(Node v) {
(2)
marked[v] := true
(3)
for all w ∈ N(v) do
(4)
if not marked[w] then
(5)
π[w] := v
(6)
DFS-ACYCLIC(w)
(7)
else if π [v]  w then
(8)
B := B  (v,w)
(9)
}
(10) }
Carsten Gutwenger
Pfad von T-Kanten +
eine B-Kante
c
e
DAP2 SS09
37
Test auf Kreisfreihet
DAP2 SS09
39
5.
 gerichteter Graph
Kante (x,y)  Aufgabe x muss abgeschlossen
werden, bevor mit y angefangen werden kann
DAP2 SS09
DAP2 SS09
38
Carsten Gutwenger
DAP2 SS09
40
Definition:
Ein DAG (directed acyclic graph) ist ein
gerichteter Graph, der keinen (gerichteten)
Kreis enthält.
Dach eindecken
Carsten Gutwenger
Carsten Gutwenger
Graph ist azyklisch!
(also keine zyklischen Abhängigkeiten)
Baugrube
Fenster
b
Grundvoraussetzung:
Dachstuhl
1.
4.
g
DAG
3.
Mauern
d
Achtung: in diesem Abschnitt
gerichtete Graphen!
Modellierung von Abhängigkeiten
2.
f
Kap. 6.4.3 Topologisches Sortieren
Theorem: Die Funktion ISACYCLIC(G) testet
einen ungerichteten Graphen G=(V,E) auf
Kreisfreiheit in Zeit Θ(|V|+|E|).
Carsten Gutwenger
a
41
Carsten Gutwenger
DAP2 SS09
42
7
Topologisches Sortieren
Warum ist dies nicht mit BFS lösbar?
Dachstuhl
Mauern
Gegeben: DAG G = (V,A)
Gesucht:
3.
2.
Topologisches Sortieren
1.
eine Sortierung v1,…,vn der Knoten
von G mit i<j für alle (vi,vj)  A
Baugrube
5.
4.
Fenster
v1
v2
v3
v4
v5
v6
v8
v7
Carsten Gutwenger
v9
graphentheoretische Distanz von Baugrube zu
Fenster = 1 (BFS), aber Fenster darf erst nach
Mauer ausgeführt werden
v10
DAP2 SS09
43
Quellen & Senken
• Eine Quelle ist ein Knoten ohne eingehende Kanten
• Eine Senke ist ein Knoten ohne ausgehende Kanten
Quelle
Senke
Carsten Gutwenger
DAP2 SS09
Carsten Gutwenger
DAP2 SS09
44
Beobachtung:
Jeder (nicht-leere) DAG G =(V,A) hat
mindestens eine Quelle und eine Senke.
Beweis: Annahme: G hat keine Senke
• Verfolge von u1 an immer ausgehende Kanten
pi := u1,u2,…,ui solange bis i > |V| oder keine
ausgehende Kante mehr existiert
• Falls i > |V|  ein Knoten zweimal auf pi
•  Kreis! Widerspruch!
• Analog für Quelle
45
Algorithmus
Carsten Gutwenger
DAP2 SS09
46
Verbesserungen
Wie finden wir effizient eine Quelle?
• Wird v gelöscht, dann können nur Zielknoten w
von Kanten (v,w) neu zu Quellen werden.
• Genügt ausgehende Nachbarmenge A -(v) zu
betrachten.
Idee:
Wähle immer Quelle und entferne sie dann
while G ist nicht leer do
Wähle eine Quelle s in G und gib sie aus
G := G - s
end while
Carsten Gutwenger
Dach eindecken
DAP2 SS09
Müssen wir Knoten wirklich löschen?
• Nein!
Verwalte Eingangsgrad in Knotenfeld indeg.
47
Carsten Gutwenger
DAP2 SS09
48
8
Algorithmus TopSort
(1)
(2)
var Queue Q
var int indeg[V]
(3)
(4)
(5)
(6)
(7)
// Initialisierung
for all v ∈ V do {
indeg[v] := d +(v)
if indeg[v] = 0 then Q.PUT(v)
}
Carsten Gutwenger
Algorithmus TopSort (2)
(8) // Hauptschleife
(9) while not Q.ISEMPTY() do {
(10)
v := Q.GET()
(11)
Gib v aus
(12)
for all (v,u) ∈ A-(v) do {
(13)
indeg[u] := indeg[u] - 1
(14)
if indeg[u] = 0 then Q.PUT(u)
(15)
}
(16) }
DAP2 SS09
49
Beispiel: TopSort
a
b
c
d
Q
a
e
j
b
f
c
DAP2 SS09
50
Analyse der Laufzeit
Ausgabe:
a
j
f
j
b
f
c
g
i
e
d
h
g
h
e d g h i
i
Carsten Gutwenger
Carsten Gutwenger
DAP2 SS09
• Initialisierung: (|V|)
(da d +(v) in konstanter Zeit abrufbar)
• Jeder Knoten kommt genau einmal in Q
 while-Schleife wird |V|-mal durchlaufen
• Die for all-Schleife (Zeile 12) wird
insgesamt für jede Kante einmal
durchlaufen: (|A|)
• Gesamtaufwand: (|V |+|A|)
51
Carsten Gutwenger
DAP2 SS09
52
Analyse TopSort
Theorem:
Der Algorithmus TopSort berechnet eine
topologische Sortierung der Knoten eines
DAGs G=(V,A) in Zeit (|V|+|A|).
Carsten Gutwenger
DAP2 SS09
53
9
Herunterladen