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