1 Folie/Blatt - Chair 11: ALGORITHM ENGINEERING

Werbung
Kap. 6.3: Traversieren von Graphen
Kap. 6.4: Elementare Graphalgorithmen
Professor Dr. Petra Mutzel
Lehrstuhl für Algorithm Engineering, LS11
Fakultät für Informatik, TU Dortmund
19. VO
DAP2
SS
2008
Petra Mutzel
19. Juni 2008
DAP2 SS08
1
Anmeldung zur Klausur
25.07.2008 um 9:00 Uhr
•  Informatik AI/KI Bacc+Diplom: BOSS System
•  Informationstechnik Diplom: ACHTUNG: bis
20.06.08: online
•  Elektrotechnik Diplom: direkt bei uns
•  Physik Bacc/Diplom: ihr Dekanat
•  Datenanalyse und Datenmanagement / Statistik
Bacc/Diplom: ihr eigenes Prüfungsamt
•  Mathematik Bacc/Diplom: erst ab 1.7. bekannt
(wahrscheinlich BOSS System)
•  Lehramt, BaMaLa: direkt bei uns?
Petra Mutzel
DAP2 SS08
2
Nachtest für Ausnahmefälle
•  Di 1. Juli 2008, 10:15 Uhr, OH14, R. 202
•  Anmeldung bis 26. Juni erforderlich via
Email an Carsten Gutwenger
•  Stoff: Alles bis inkl. Hashing (inkl.1.-10.
Übungsblatt)
•  Teilnahmevoraussetzungen:
•  Attest/Entschuldigt beim 1. oder 2. Übungstest
•  oder besondere Härtefälle anerkannt in meiner
Sprechstunde Di 24.6.08,14:15 Uhr-15:15 Uhr
Petra Mutzel
DAP2 SS08
3
Motivation
Heute braucht es keine Motivation,
denn:
DFS
Spielereien
mit
Petra Mutzel
DAP2 SS08
4
Überblick
•  Darstellung von Graphen im Rechner
•  Traversieren von Graphen:
–  Breitensuche (BFS)
–  Tiefensuche (DFS)
•  Elementare Graphalgorithmen:
–  Zusammenhangskomponenten
–  Kreise in Graphen
Petra Mutzel
DAP2 SS08
5
Darstellung von Graphen im Rechner:
Statische Graphen
•  Im Folgenden sei V={v1,v2,…,vn}
•  1. Möglichkeit: Adjazenzlisten
•  Idee: Speichere für jeden Knoten seine
Nachbarmenge in einer Liste
•  Realisierung: z.B. Knoten in Array und
Nachbarkanten jedes Knotens als einfach
verkettete Liste
Petra Mutzel
DAP2 SS08
6
Darstellung von Graphen im Rechner:
Statische Graphen
•  2. Möglichkeit: Adjazenzmatrix
•  Idee: Eine VxV Matrix enthält 0/1-Einträge für
jedes Knotenpaar {u,v}
•  Realisierung:
•  Sei M=(mi,j) eine n x n Matrix mit
mij:=1 falls (vi,vj)∈E,
und
mij:=0
sonst.
•  bei Mehrfachkanten schreibe statt 1 die Anzahl
der Kanten
Petra Mutzel
DAP2 SS08
7
Darstellung gerichteter Graphen
Adjazenzlisten
Adjazenzmatrix
Petra Mutzel
DAP2 SS08
8
Darstellung ungerichteter Graphen
Adjazenzlisten
Adjazenzmatrix
ist symmetrisch: nur Speicherung
Petra Mutzel
DAP2 Hälfte
SS08
9
der oberen
Diskussion
HIER: ab jetzt Adjazenzlisten
für dünne Graphen vorzuziehen!
Adjazenzliste:
•  Speicherplatzverbrauch: linear: Θ(|V|+|E|)
•  Zeit für Aufbau: linear: Θ(|V|+|E|)
•  Abfrage, ob Kante (u,v) existiert: Θ(d(v))
•  Iteration über alle Nachbarn von v∈V: Θ(d(v))
Adjazenzmatrix:
•  Speicherverbrauch immer quadratisch: Θ(|V|2)
•  Zeit für Aufbau: immer quadratisch: Θ(|V|2)
•  Abfrage, ob Kante (u,v) existiert: Θ(1)
•  Iteration über alle Nachbarn von v∈V: Θ(|V|)
Petra Mutzel
DAP2 SS08
10
10
Definitionen
•  Die Dichte (density) eines Graphen G ist
das Verhältnis |E| / |V|.
•  G heißt dünn, falls seine Dichte O(1) ist
•  G heißt dicht, falls seine Dichte Ω(|V|) ist.
Petra Mutzel
DAP2 SS08
11
11
Darstellung von Graphen im Rechner:
Dynamische Graphen
•  Dynamisch unter den Operationen:
–  Hinzufügen neuer Knoten und Kanten
–  Entfernen von Knoten und Kanten
•  Idee: für gerichtete Graphen:
•  Inzidenzlisten: speichere ein- und ausgehende
Knoten bei v
•  Knoten in doppelt verketteter Liste (damit
Entfernen in konstanter Zeit)
•  Inzidenzlisten in doppelt verketteten Listen
Petra Mutzel
DAP2 SS08
12
12
Realisierung Dynamische Graphen:
Liste für die Knoten
struct Node
var Node prev
var Node next
var Edge outHead
var Edge inHead
var int index
end struct
// Vorgänger Knotenliste
// Nachfolger in Knotenliste
// Listenanfang ausgeh. Kanten
// Listenanfang eingeh. Kanten
// fortlaufender Index
Petra Mutzel
DAP2 SS08
13
13
Realisierung Dynamische Graphen:
Liste für die Kanten
struct Edge
var Edge prevOut
var Edge nextOut
var Edge prevIn
var Edge nextIn
var node source
var node target
end struct
//Vorgänger in Liste ausg. Kanten
//Nachfolger in Liste ausg. Kanten
// Vorgänger in Liste eing. Kanten
// Nachfolger in Liste eing. Kanten
// Anfangsknoten der Kante
// Endknoten der Kante
Achtung: jeder Kanteneintrag ist genau einmal in Liste enthalten
Petra Mutzel
DAP2 SS08
14
14
Darstellung von Graphen im Rechner:
Dynamische Graphen
Legende
Liste der eingehenden Kanten:
15
Analyse Dynamischer Graphen
• 
• 
• 
• 
• 
• 
• 
• 
• 
Speicherplatzverbrauch: linear: Θ(|V|+|E|)
Zeit für Aufbau: linear: Θ(|V|+|E|)
Abfrage, ob Kante (u,v) existiert: Θ(d(v))
Iteration über alle Nachbarn von v∈V: Θ(d(v))
Iteration über alle ausg. Kanten von v∈V: Θ(d-(v))
Iteration über alle eing. Kanten von v∈V: Θ(d+(v))
Einfügen eines Knotens bzw. Kante: Θ(1)
Entfernen einer Kante: Θ(1)
Entfernen eines Knotens: Θ(d(v))
Man geht davon aus, dass man jeweils Zeiger auf die Knoten
und beim Entfernen auch auf die Kanten gegeben hat 16
Kap. 6.3 Traversieren von Graphen
Traversieren: systematisches Durchwandern
von Graphen
HIER: ungerichtete Graphen
Def.: Der graphentheoretische Abstand zweier
Knoten u, v eines ungerichteten Graphen G ist die
Länge des kürzesten Weges von u nach v, falls
ein solcher existiert, sonst ∞.
Achtung: hierbei werden keine vorgegebenen
Kantenlängen bzw. Kantengewichte berücksichtigt.
Kap. 6.3.1 Breitensuche (BFS)
engl.: Breadth-first-search, BFS
Idee: besuche die Knoten nach aufsteigendem
graphentheoretischen Abstand zu einem vorher
festgelegten Startknoten.
1.  Fall: Wir sehen v zum ersten Mal (von u aus):
• 
Dann muss dist(v) um genau 1 größer sein als
dist(u).
• 
Wir können v besuchen, nachdem wir alle
bisher gesehenen Knoten besucht haben.
2.  Fall: wir haben v schon gesehen → nichts zu tun
Petra Mutzel
DAP2 SS08
18
18
Breitensuche (BFS)
Methode:
(1)  Starte am Knoten u:=s. Sei Q:=∅
eine
Queue.
(2)  Für alle Knoten v∈N(u) // erforsche Knoten u
(3)  Falls wir v zum ersten Mal sehen:
(4) 
markiere v als „gesehen“
(5) 
dist(v):=dist(u)+1; merke Vorgänger;
(6) 
hänge v hinten an Q an.
(7)  Sei u der nächste Knoten in Q. Gehe zu (2)
dist(v) enthält den graphentheoretischen Abstand
von u nach v; π(v) den Vorgänger des kürz. Weges
Petra Mutzel
DAP2 SS08
19
19
Beispiel für BFS
1
1
c
b
Petra Mutzel
DAP2 SS08
20
20
Beispiel für BFS
1
1
2
2
c
b
e
d
Petra Mutzel
DAP2 SS08
21
21
Beispiel für BFS
1
1
2
2
b
e
d
Petra Mutzel
DAP2 SS08
22
22
Beispiel für BFS
1
1
2
3
2
3
e
d
Petra Mutzel
g
f
DAP2 SS08
23
23
Beispiel für BFS
1
1
2
3
2
3
d
Petra Mutzel
g
f
DAP2 SS08
24
24
Beispiel für BFS
1
1
2
3
2
3
g
Petra Mutzel
f
DAP2 SS08
25
25
Beispiel für BFS
1
1
2
2
3
3
f
Petra Mutzel
DAP2 SS08
26
26
Beispiel für BFS
Breitensuche entspricht einer level-order
Traversierung in diesem BFS-Baum.
1
1
2
2
3
3
Die orangen Kanten (diejenigen Kanten (u,v), die
zum ersten Mal v besuchen) bilden einen Baum:
den BFS-Baum (oder BFS-Wald, wenn G nicht
zusammenhängend ist)
Algorithmus BFS(s)
Sei G=(V,E) ungerichteter Graph, s,u,v: Knoten
(1)  for all v∈V \ {s} do {
marked[v]:=0; dist[v]:=∞}
(2)  Q.put(s); marked[s]:=1; dist[s]:=π[s]:=0
(3)  while not Q.ISEMPTY() do {
(4)  u:=Q.GET()
(5)  for all v∈N(u)
do
{
(6)  if not
marked[v]
then
{
(7)  Q.Put(v)
(8) 
marked[v]:=1
(9) 
dist[v]:=dist[u]+1; π[v]:=u
(10) 
}
}
}
Petra Mutzel
DAP2 SS08
30
30
BFS-Baum
•  Im Feld π[v] werden die Vorgänger von v gespeichert.
•  Die Kanten (π(v),v) bilden einen Baum mit Wurzel s.
•  Die Höhe des BFS-Baumes mit Startknoten s ist
eindeutig bestimmt.
•  Die Tiefe eines Blattes v entspricht dem
graphentheoretischen Abstand von v zu s
s
1
Wurzel
1
2
2
3
3
Petra Mutzel
DAP2 SS08
31
31
Analyse von BFS
• 
• 
• 
• 
Initialisierung: Θ(|V|)
Die while-Schleife wird für jeden von s aus
erreichbaren Knoten genau einmal durchlaufen,
da jeder Knoten höchstens einmal in die Queue
kommt.
Die for all-Schleife durchläuft für jeden Knoten die
Liste seiner Nachbarn N(v), das ist also jeweils
Θ(d(v)) Aufwand
Gesamtaufwand: Θ(|V|)+∑ Θ(d(v))= Θ(|V|+|E|),
v∈V
da im Worst Case alle Knoten von s aus erreichbar
sein können
Problem USSSP
Unweighted Single-Source Shortest Path
(USSSP):
•  Gegeben: ungerichteter Graph G=(V,E)
•  Gesucht: kürzester Weg von s zu jedem
Knoten in G. Petra Mutzel
DAP2 SS08
33
33
Breitensuche (BFS)
Theorem: Sei G=(V,E) ein ungerichteter
Graph und s∈V.
Dann
löst
der
Algorithmus
BFS(s) das Unweighted Single-Source
Shortest Path (USSSP) für Startknoten s in
Zeit O(|V|+|E|).
Petra Mutzel
DAP2 SS08
34
34
Kap. 6.3.2 Tiefensuche
Petra Mutzel
DAP2 SS08
35
35
Tiefensuche (DFS)
engl.: Depth-first-search, DFS
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 zu 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.
Petra Mutzel
DAP2 SS08
36
36
Tiefensuche DFS
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.
•  Der folgende Algorithmus DFS(G) durchwandert
alle Knoten des Graphen.
•  Im Feld π[w] wird jeweils der Vorgänger von w
(also v) gespeichert.
Petra Mutzel
DAP2 SS08
37
37
Algorithmus DFS(G)
Sei G=(V,E) ungerichteter Graph, v,w: Knoten
(1)  for all v∈V do {
marked[v]:=0; π[v]:=nil}
(2)  for all v∈V do {
(3)  if not
marked[v] then DFS-VISIT(v)
(4)  }
(5)  procedur DFS-VISIT(Node v)
(6)  marked[v]:=1
(7)  for all w∈N(v)
do
(8)  if not
marked[w]
then {
(9) 
π[w]:=v
(10) 
DFS-VISIT(w)
(11) 
} Beispiel für DFS
2
c
Petra Mutzel
DAP2 SS08
39
39
Beispiel für DFS
2
3
e
c
Petra Mutzel
DAP2 SS08
40
40
Beispiel für DFS
g
e
c
2
3
Petra Mutzel
4
DAP2 SS08
41
41
Beispiel für DFS
f
g
e
c
2
3
4
5
Petra Mutzel
DAP2 SS08
42
42
Beispiel für DFS
f
g
e
c
2
3
4
5
Petra Mutzel
DAP2 SS08
43
43
Beispiel für DFS
g
e
c
2
3
4
5
Petra Mutzel
DAP2 SS08
44
44
Beispiel für DFS
d
e
c
2
3
6
4
5
Petra Mutzel
DAP2 SS08
45
45
Beispiel für DFS
b
d
e
c
2
7
3
6
4
5
Petra Mutzel
DAP2 SS08
46
46
Beispiel für DFS
b
d
e
c
2
7
3
6
4
5
Petra Mutzel
DAP2 SS08
47
47
Beispiel für DFS
d
e
c
2
7
3
6
4
5
Petra Mutzel
DAP2 SS08
48
48
Beispiel für DFS
2
e
c
7
3
6
4
5
Petra Mutzel
DAP2 SS08
49
49
Beispiel für DFS
2
c
7
3
6
4
5
Petra Mutzel
DAP2 SS08
50
50
Beispiel für DFS
2
7
3
6
4
5
Petra Mutzel
DAP2 SS08
51
51
Beispiel für DFS
2
7
6
3
4
5
Die orangen Kanten (diejenigen Kanten (u,v), die
zum ersten Mal v besuchen) bilden einen Baum:
den DFS-Baum (G zusammenhängend, sonst Wald)
Sei G
zusammenhängend
DFS-Baum
DFS-Baum besteht aus
•  Baumkanten (tree edges, T-Kanten): (π(v),v)
•  Rückwärtskanten (back edges, B-Kanten): s.u.
• 
• 
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
2
3
4
v
7
6
u 5
Sei G
zusammenhängend
DFS-Baum
• 
• 
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
2
3
4
v
7
6
u 5
Analyse von DFS
• 
• 
• 
• 
• 
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
Petra Mutzel
DAP2 SS08
57
57
BFS-Baum vs. DFS-Baum
BFS-Baum
1
2
3
Höhe eindeutig
1
2
2
3
3
4
DFS-Baum
7
6
Petra Mutzel
5
DAP2 SS08
58
58
BFS & DFS
BFS-Baum
DFS-Baum
Petra Mutzel
DAP2 SS08
59
59
Kap. 6.4 Elementare
Graphenalgorithmen
Kap. 6.4.1 Komponenten eines Graphen
Zusammenhangskomponenten
Petra Mutzel
DAP2 SS08
60
60
Definitionen (Zusammenhang)
•  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´.
Petra Mutzel
DAP2 SS08
61
61
Komponenten eines Graphen
C1
C3
C2
C4
T-Kanten des DFS-Waldes
Petra Mutzel
DAP2 SS08
62
62
Bestimmen der
Zusammenhangskomponenten
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
Petra Mutzel
DAP2 SS08
63
63
Algorithmus COMPONENTS(G)
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 not
marked[v]
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 not
marked[w]
then
(12) 
DFS-COMP(w)
Bestimmen der
Zusammenhangskomponenten
Theorem: Der Algorithmus COMPONENTS(G)
bestimmt die Zusammenhangskomponenten
eines Graphen G=(V,E) in Zeit Θ(|V|+|E|).
Petra Mutzel
DAP2 SS08
65
65
Kap. 6.4.2 Kreise in Graphen
•  Aufgabe: Gegeben ist ein ungerichteter Graph
G=(V,E). Enthält G einen Kreis?
•  Idee: mittels DFS
Petra Mutzel
DAP2 SS08
66
66
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.
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.
Petra Mutzel
DAP2 SS08
67
67
Kreise und DFS
•  Methode: Erweitere DFS um Speicherung der
B-Kanten: sobald wir von v aus auf einen
markierten Knoten u treffen, haben wir eine
B-Kante gefunden, falls u nicht der direkte
Vorgänger (Elter) von v ist.
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.
Petra Mutzel
DAP2 SS08
68
68
Algorithmus ISACYCLIC(G)
Sei G=(V,E) ungerichteter Graph
(1)  function ISACYCLIC(Graph G=(V,E)) : bool {
(2) 
B := ∅
(3) 
for all v∈V do {
marked[v]:=0; π(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)  }
Petra Mutzel
DAP2 SS08
69
69
Algorithmus ISACYCLIC(G) ff
(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)  }
Petra Mutzel
DAP2 SS08
70
70
Welche Kreise werden gefunden?
Pfad von T-Kanten +
eine B-Kante
a
c
e
f
d
g
b
Petra Mutzel
DAP2 SS08
75
75
Test auf Kreisfreihet
Theorem: Die Funktion ISACYCLIC(G) testet
einen ungerichteten Graphen G=(V,E) auf
Kreisfreiheit in Zeit Θ(|V|+|E|).
Petra Mutzel
DAP2 SS08
76
76
Petra Mutzel
DAP2 SS08
77
77
Zum Ausschneiden und Üben
Petra Mutzel
DAP2 SS08
78
78
Q
a
d
e
b
f
c
g
Herunterladen