Algorithmen und Datenstrukturen

Werbung
Wiederholung Graph
gerichteter Graph G = (V , E) mit E ⊆ {(u, v ) | u, v ∈ V }
Graph mit Knotenmarkierung in Menge C (gerichtet oder
ungerichtet)
G = (V , E, l) mit l : V → C
Graph mit Kantenmarkierung in Menge C
(gerichtet oder ungerichtet)
G = (V , E, l) mit l : E → C (Gewichte)
Repräsentation als
I
I
Matrix (sinnvoll für dichte Graphen)
explizite Darstellung der Relation:
I
I
Liste von Kanten
Adjazenzliste (Knoten, Liste aller Nachfolger)
155
Pfade, Kreise, SCC
Weg in G = (V , E): Folge (p1 , . . . , pn ) ∈ V n mit
I ∀i ∈ {1, . . . , n − 1} : (pi , pi+1 ) ∈ E
Weg von u nach v :
Weg (p1 , . . . , pn ) mit p1 = u und pn = v
Pfad in G = (V , E): Folge (p1 , . . . , pn ) ∈ V n mit
I ∀i ∈ {1, . . . , n − 1} : (pi , pi+1 ) ∈ E und
I ∀i, j ∈ {1, . . . , n − 1} : (i < j → pi 6= pj )
Pfad von u nach v :
Pfad (p1 , . . . , pn ) mit p1 = u und pn = v
Kreis in G = (V , E): Folge (p1 , . . . , pn ) ∈ V n mit
I ∀i ∈ {1, . . . , n − 1} : (pi , pi+1 ) ∈ E und
I ∀i, j ∈ {1, . . . , n − 1} : (i < j → pi 6= pj ) und
I (pn , p1 ) ∈ E
SCC (starke Zusammenhangskomponente)
(⊆-)maximale Menge S ⊆ V , wobei für alle
u, v ∈ S Pfade von u nach v und von v nach u
existieren
156
Wiederholung – Baumdurchquerungen
Ziel: Besuch aller Knoten eines Graphen
Preorder-, Postorder-, Inorder-Durchquerung
Jede Durchquerungsreihenfolge definiert eine lineare Ordnung
auf der Knotenmenge.
Praktikum-Aufgabe: Reihenfolge des Knotenbesuches durch
Hilfs-Datenstruktur zur Verwaltung der noch zu besuchenden
Knoten
Queue Ebenen-Durchlauf (level-order)
Stack Preorder-Durchlauf des gespiegelten Baumes
Priority-Queue Besuch der Knoten entsprechend ihrer Priorität
(erreichbare Knoten mit höchster Priorität zuerst)
157
Tiefendurchlauf (DFS) für Graphen
Idee: Weitestmögliche Verfolgung von Pfaden
Eingabe: Graph G = (V , E)
Ausgabe: Folge S = (v1 , . . . , vn ) aller Knoten in V
Algorithmus Tiefensuche(G):
W := V , S = ∅
solange W 6= ∅ wiederholen:
1. u ∈ W auswählen und aus W entfernen, u an S anhängen
2. für alle Nachfolger v von u mit v 6∈ S:
Tiefensuche mit Startknoten v
anschaulich durch schrittweise Umfärbung der Knoten in G:
W=unentdeckt, R=entdeckt, S=erledigt
158
Breitendurchlauf (BFS) für Graphen
Idee: Besuch der Knoten geordnet nach wachsender
Entfernung von einem Startknoten
Eingabe: Graph G = (V , E)
Ausgabe: Folge S = (v1 , . . . , vn ) aller Knoten in V
Breitensuchalgorithmus:
W := V , S = ∅
solange W 6= ∅ wiederholen:
1. u ∈ W auswählen,
2. R = {u} (Queue), u aus W entfernen, u an S anhängen
3. solange R 6= ∅ wiederholen:
3.1 v=dequeue(R)
3.2 für alle Nachfolger v 0 von v :
falls v 0 6∈ S ∪ R: enqueue(R,v 0 ), v 0 aus W entfernen
anschaulich durch schrittweise Umfärbung der Knoten in G:
W=unentdeckt, R=entdeckt, S=erledigt
enqueue = Umfärbung W → R, dequeue = Umfärbung R → S
159
Graph-Durchquerungen als Baum-Durchquerungen
Ziel: Besuch aller Knoten eines Graphen
Voraussetzung (zunächst): ∀v ∈ V ∃ Pfad von u nach v
Expansion X (G, u) eines Graphen G = (V , E) aus einem
Knoten u ∈ V :
IA u hat keine Nachfolger:
X (G, u) = node(u, [])
IS u hat Nachfolger u1 , . . . , un :
X (G, u) = node(u, [X (G, u1 ), . . . , X (G, un )])
(Knoten von G können in X (G, u) mehrfach vorkommen)
Wege von u in G = Wege u in X (G, u)
Tiefendurchlauf (depth-first-traversal) in G =
Preorder-Durchlauf in X (G, u) ohne Besuch der
schon besuchten Knoten
Breitendurchlauf (breadth-first-traversal) in G =
Level-order-Durchlauf in X (G, u) ohne Besuch der
schon besuchten Knoten
160
Gerüste
Graph-Durchquerungen für allgemeine Graphen G = (V , E)
(nicht notwendig zusammenhängend)
Gerüst für einen Graphen G = (V , E):
Wald G0 = (V , E 0 ) mit E 0 ⊆ E
(endliche Menge von Bäumen)
Algorithmus zur Bestimmung eines Gerüstes für G:
Eingabe: Graph G = (V , E)
Ausgabe: Gerüst G0 für G
Algorithmus:
1. Knotenmenge K = V , G0 = ∅
2. solange K 6= ∅ wiederholen:
2.1
2.2
2.3
2.4
Knoten u aus K wählen
Graph GK = (K , E ∩ K 2 ) (Einschränkung von G auf K )
X (GK , u) in G0 einfügen,
alle Knoten in X (G, u) aus K entfernen
Durchlauf eines Graphen G =
Durchlauf aller Bäume eines Gerüstes G0 für G
161
Topologische Ordnungen
(Anwendung für Tiefensuche)
gerichteter kreisfreier Graph (DAG) G = (V , E)
topologische Ordnung für G:
Darstellung von V als Folge (u1 , . . . , un ) mit
∀(u, v ) ∈ E : u = ui ∧ v = uj ∧ i < j
(lineare Ordnung (V , R) mit E ⊆ R)
Topologischer-Ordungs-Algorithmus für DAG:
Eingabe: DAG G = (V , E)
Ausgabe: topologische Ordnung S = (u1 , . . . , un ) für G
Algorithmus:
S=∅
I
Tiefendurchlauf auf G
I
nach Erledigung jedes Knotens v :
v vorn in Liste S einfügen
162
Starke Zusammenhangskomponenten (SCC)
(Anwendung für Tiefensuche)
Idee: Die SCC eines Graphen G sind genau die SCC des
transponierten Graphen GT (Kantenrichtung umgekehrt)
Algorithmus zur Bestimmung der SCC eines Graphen:
Eingabe: Graph G = (V , E)
Ausgabe: Menge S = {S1 , . . . , SK } aller SCC in G
Algorithmus:
u = leere Queue
I
Tiefendurchlauf auf G
I
nach Erledigung jedes Knotens v : enqueue(u,v)
I
Tiefendurchlauf auf GT mit Knotenreihenfolge aus u
I
SCC von G sind genau die Knotenmengen der
Tiefendurchlauf-Bäume
163
Wiederholung – Algorithmus von Dijkstra
(Anwendung für Duchlauf mit Priority-Queue)
Ziel: Bestimmung kürzester Pfade von einem Knoten eines
Graphen zu allen erreichbaren Knoten
Eingabe: gewichteter Graph G = (V , E, l) (positive Gewichte),
u∈V
Ausgabe: S = {(v , lv ) | v ∈ V } mit
lv =Länge des kürzesten Pfades von u nach v
Algorithmus:
1. Q = {(u, 0)} (Priority-Queue), S = ∅
2. wiederhole solange Q 6= ∅:
2.1 deletemin(Q)=(Q’,(v,w)),
2.2 falls v 6∈ S:
2.2.1 S := S ∪ {(v , w)}
2.2.2 für alle Nachfolger v 0 von v :
enqueue (Q, (v , w + l(v , v 0 )))
(kleineres Gewicht, falls (v 0 , w 0 ) ∈ Q mit w 0 > w + l(v , v 0 ))
164
Herunterladen