Teil III: Graphenalgorithmen

Ähnliche Dokumente
Ein Graph ist ein Paar (V,E), wobei V eine Menge von Knoten und E eine Menge von Kanten (v,w) mit v,w in V ist.

Definition Ein gerichteter Graph G = (V, E) ist ein Graph von geordneten Paaren (u, v) mit u V und v V.

Routing Algorithmen. Begriffe, Definitionen

Graphen: Datenstrukturen und Algorithmen

Algorithmen und Datenstrukturen 2

ADS: Algorithmen und Datenstrukturen 2

Algorithmen und Datenstrukturen 2

Vorlesung Informatik 2 Algorithmen und Datenstrukturen. (20 Graphen) T. Lauer

Algorithmen und Datenstrukturen 2

8 Diskrete Optimierung

Informatik 11 Kapitel 2 - Rekursive Datenstrukturen

Technische Universität Wien Institut für Computergraphik und Algorithmen Arbeitsbereich für Algorithmen und Datenstrukturen

Kürzeste Wege in Graphen. Maurice Duvigneau Otto-von-Guericke Universität Fakultät für Informatik

4. Kreis- und Wegeprobleme Abstände in Graphen

Datenstrukturen & Algorithmen

3. Musterlösung. Problem 1: Boruvka MST

5.2 Das All-Pairs-Shortest-Paths-Problem (APSP-Problem) Kürzeste Wege zwischen allen Knoten. Eingabe: Gerichteter Graph G =(V, E, c)

Universität Bremen. Graphenalgorithmen. Thomas Röfer. Begriffe Repräsentationen Kürzeste Wege Minimale spannende Bäume

Klausur Informatik B April Teil I: Informatik 3

Grundlagen Datenstrukturen Transitive Hülle Traversierung Kürzeste Wege Spannender Baum Max. Fluss Zuordnungen. 6. Graphen

Grundbegriffe der Informatik

Theoretische Informatik 1 WS 2007/2008. Prof. Dr. Rainer Lütticke

Vorlesung Datenstrukturen

Breiten- und Tiefensuche in Graphen

Graphen. Leonhard Euler ( )

1 topologisches Sortieren

Grundlagen der Informatik. Prof. Dr. Stefan Enderle NTA Isny

Eine Baumstruktur sei folgendermaßen definiert. Eine Baumstruktur mit Grundtyp Element ist entweder

Grundbegriffe der Informatik

Vorlesung 4 BETWEENNESS CENTRALITY

Minimal spannende Bäume

Binary Decision Diagrams (Einführung)

Lernmodul 2 Graphen. Lernmodul 2: Geoobjekte und ihre Modellierung - Graphen

1. Einfach verkettete Liste unsortiert 2. Einfach verkettete Liste sortiert 3. Doppelt verkettete Liste sortiert

Customization (Zuschneiden)

Graphen. Formale Methoden der Informatik WiSe 2010/2011 teil 2, folie 1 (von 60)

Fully dynamic algorithms for the single source shortest path problem.

Diskrete Mathematik. Sebastian Iwanowski FH Wedel. Kap. 6: Graphentheorie

Effiziente Algorithmen und Datenstrukturen: Kürzeste Wege

Aufgabe 4.2 Sei G = (V, E, l) ein ungerichteter, gewichteter und zusammenhängender Graph.

Grundlagen der Pfadplanung

Algorithmen und Datenstrukturen Graphen - Einführung

DATENSTRUKTUREN UND ALGORITHMEN

Was bisher geschah ADT Menge mit Operationen: Suche nach einem Element Einfügen eines Elementes Löschen eines Elementes Realisierung durch

Was bisher geschah. 1. Zerlegung in monotone Polygone 2. Triangulierung der monotonen Teilpolygone

Kapitel 4: Dynamische Datenstrukturen. Algorithmen und Datenstrukturen WS 2012/13. Prof. Dr. Sándor Fekete

Algorithmen und Datenstrukturen

Effiziente Algorithmen und Datenstrukturen I. Kapitel 9: Minimale Spannbäume

2. Übungsblatt zu Algorithmen II im WS 2016/2017

Algorithmen und Datenstrukturen Suchbaum

Programmiertechnik II

Anmerkungen zur Übergangsprüfung

Uninformierte Suche in Java Informierte Suchverfahren

Datenstrukturen. Mariano Zelke. Sommersemester 2012

WS 2009/10. Diskrete Strukturen

SS11 Effiziente Algorithmen 5. Kapitel: Dynamische Programmierung

Algorithmen II Vorlesung am

Teil II: Prioritätslisten (Priority Queues)

Graphenalgorithmen I

Gliederung. 5. Compiler. 6. Sortieren und Suchen. 7. Graphen

14. Rot-Schwarz-Bäume

MafI I: Logik & Diskrete Mathematik (F. Hoffmann)

κ(k) k K S Algorithmus zur Bestimmung eines spannenden Baumes mit minimalen Kosten (Kruskal, 1965).

C++, LEDA und STL Visualisierung minimal/maximal aufspannender Bäume

TECHNISCHE UNIVERSITÄT MÜNCHEN FAKULTÄT FÜR INFORMATIK

Effiziente Algorithmen I

Grundlagen der Programmierung 2. Bäume

3.2 Binäre Suche. Usr/local/www/ifi/fk/menschen/schmid/folien/infovk.ppt 1

Bäume. Informatik B - Objektorientierte Programmierung in Java. Vorlesung 10: Collections 4. Inhalt. Bäume. Einführung. Bäume.

Vollständiger Graph. Definition 1.5. Sei G =(V,E) ein Graph. Gilt {v, w} E für alle v, w V,v w, dann heißt G vollständig (complete).

Dynamische Mengen. Realisierungen durch Bäume

Literatur. Dominating Set (DS) Dominating Sets in Sensornetzen. Problem Minimum Dominating Set (MDS)

Proseminar Online Algorithmen, Prof. Dr. Rolf Klein

9. Heuristische Suche

1. Motivation / Grundlagen 2. Sortierverfahren 3. Elementare Datenstrukturen / Anwendungen 4. Bäume / Graphen 5. Hashing 6. Algorithmische Geometrie

Kapitel 9. Komplexität von Algorithmen und Sortieralgorithmen

11.1 Grundlagen - Denitionen

Fortgeschrittene Programmiertechnik Klausur WS 2014/15 Angewandte Informatik Bachelor

Kombinatorische Optimierung

ADS: Algorithmen und Datenstrukturen 2

Einführung in Heuristische Suche

1. Motivation / Grundlagen 2. Sortierverfahren 3. Elementare Datenstrukturen / Anwendungen 4. Bäume / Graphen 5. Hashing 6. Algorithmische Geometrie

MB2-ALG, SS15 Seite 1 Hauptklausur, geschrieben am

Name: Seite 2. Beantworten Sie die Fragen in den Aufgaben 1 und 2 mit einer kurzen, prägnanten Antwort.

Ausarbeitung zum Modulabschluss. Graphentheorie. spannende Bäume, bewertete Graphen, optimale Bäume, Verbindungsprobleme

Graph Paar (V,E) V: nichtleere Menge von Knoten (vertex) E: Menge von Kanten (edges): Relation (Verbindung) zwischen den Knoten

Programmiertechnik II

Einführung in die Graphentheorie. Monika König

Algorithmen und Datenstrukturen (WS 2007/08) 63

Das Briefträgerproblem

Teil XII. Datenstrukturen: Bäume, Stacks und Queues. Scientific Computing in Computer Science, Technische Universität München

f h c 7 a 1 b 1 g 2 2 d

Algorithmen und Datenstrukturen 2-2. Seminar -

Ferienkurs zur algorithmischen diskreten Mathematik Kapitel 3: Minimal aufspannende Bäume und Matroide

13. Binäre Suchbäume

2. Repräsentationen von Graphen in Computern

Undirected Single-Source Shortest Paths with Positive Integer Weights in Linear Time

Algorithmen und Datenstrukturen 1

Fortgeschrittene Programmiertechnik Klausur SS 2015 Angewandte Informatik Bachelor

Konzepte der Informatik

Transkript:

Teil III: Graphenalgorithmen Anwendungen Definitionen Datenstrukturen für Graphen Elementare Algorithmen Topologisches Sortieren Kürzeste Wege Minimal aufspannende Bäume Flüsse in Netzwerken Zusammenhangskomponenten Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08 -

Kommunikationsnetze () Menge von Rechnern, die mit Leitungen verbunden sind. Beispiele Knoten (Rechner) Kante (Leitung) Vollständig vernetzte Struktur Sternstruktur Ringstruktur Busstruktur Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08 -

Kommunikationsnetze () Zuverlässigkeit von Kommunikationsnetzen lässt sich bemessen durch: Verbindungszusammenhang: Minimale Anzahl von Verbindungen, bei deren Ausfall die Kommunikation zwischen irgendwelchen Knotenpaaren unterbrochen wird. Knotenzusammenhang: Minimale Anzahl von Knoten, bei deren Ausfall die Kommunikation zwischen irgendwelchen Knotenpaaren unterbrochen wird. Algorithmus Flüsse in Netzwerken. Routing-Problem Bestimme von einem Rechnerknoten den günstigsten Weg zum Zielknoten. Die Güte einer Verbindungskante ist dabei beispielsweise durch seine Paketkapazität definiert. Algorithmus kürzeste Wege in Graphen Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08 -

Problemstellung Routenplanung Finde in einem Straßennetz die kürzeste Verbindung (Länge bzw. Fahrtzeit) von einer Stadt A zu einer Stadt B. 6 7 8 8 6 7 0 5 Algorithmus kürzeste Wege in Graphen Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08 -

Problemstellung Netzplanung Zwischen n Orten soll ein Versorgungsnetz (Kommunikation, Strom, Wasser, etc.) aufgebaut werden, so dass je Orte direkt oder indirekt miteinander verbunden sind. Die Verbindungskosten zwischen Orte seien bekannt. Gesucht ist ein Versorgungsnetz mit den geringsten Kosten. 7 6 5 Orte mit Verbindungskosten Günstigstes Versorgungsnetz Algorithmus minimal aufspannende Bäume Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-5

Zyklenfreiheit bei gerichteten Graphen () Beispiel: Ausschnitt aus Vererbungsgraph für stream-klassen in C++ ios istream ostream iostream fstream strstream Beispiel: include-graph in C mod.h Dictionary.h set.h string.h Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-6

Zyklenfreiheit bei gerichteten Graphen () Beispiel: Montageanleitung für Schrank Füße an Boden montieren Linke Seitenwand montieren Rechte Seitenwand montieren Decke montieren Scharniere an Türen montieren Linke Türe an linke Seitenwand montieren Rechte Türe an rechte Seitenwand montieren Algorithmus topologische Sortierung Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-7

Internet-Suchmaschinen () Web-Seiten mit ihren Verweisen A C B D Problemstellung: Indexierung Besuche alle Internetseiten, extrahiere Schlüsselwörter und speichere diese in einen Index. Algorithmus Tiefensuche Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-8

Internet-Suchmaschinen () Problemstellung: Relevanz von Internetseiten Bei Eingabe eines Suchbegriffs durchsuchen die Suchmaschinen ihren Index. Die gefundenen Internetseiten werden üblicherweise nach Relevanz sortiert ausgegeben. Problem: Stelle die Relevanz von Internetseiten fest. PageRank-Algorithmus von Page und Prin (s. [Turau]) ) Berechne für jede Internetseite w den PageRank r(w) nach folgender Formel: r w = α + α * r(v) l(v) 0 5 678 9:; < l(v) = Anzahl der ausgehenden Links von v a Î [0,] ist Dämpfungsfaktor v w v n ) Wiederhole Schritt ) solange, bis r(w) für alle Seiten hinreichend konvergiert. Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-9

Internet-Suchmaschinen () Beispiel: Für das Beispiel-Netz ergeben sich mit a = 0.5 folgende Gleichungen: r(a) = 0.5 + 0.5*r(B) r(b) = 0.5 + 0.5*r(A)/ r(c) = 0.5 + 0.5*(r(A)/ + r(d)) r(d) = 0.5 + 0.5*r(C) Beginnt man mit den Initialisierungswerten r(w) = und wendet man die Gleichungen iterativ an, ergeben sich bereits nach Iterationen stabile Werte: A B C D Iterationen r(a) r(b) r(c) r(d) 0 0.75.5 0.875 0.75.5.5 0.875 0.788.8.5 0.859 0.788.8.06 5 0.859 0.78.85.06 Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-0

Teil III: Graphenalgorithmen Anwendungen Definitionen Datenstrukturen für Graphen Elementare Algorithmen Topologisches Sortieren Kürzeste Wege Minimal aufspannende Bäume Flüsse in Netzwerken Zusammenhangskomponenten Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08 -

Gerichteter Graph Ein gerichteter Graph G = (V, E) besteht aus einer Menge V von Knoten (engl. vertices) und einer Menge E V V von Kanten (engl. edges). Eine Kante ist ein geordnetes Paar von Knoten (v,w). Die Kanten sind gerichtet: die Kante (v,w) geht von Knoten v nach Knoten w. In den graphischen Darstellungen werden Pfeile verwendet. Kanten der Form (v,v) heißen Schlingen. Gerichtete Graphen werden auch Digraphen genannt. v Knoten v v Kante v v 5 V = { v, v, v, v, v 5 E = { (v,v ), (v,v ), (v,v ), (v,v ), (v,v ), (v 5,v ) Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08 -

Ungerichteter Graph Bei einem ungerichteter Graph G = (V, E) haben die Kanten keine Richtung. Eine Kante ist gegeben durch ein ungeordnetes Paar von Knoten (v,w). Es gilt (v,w) = (w,v). Ein ungeordnetes Paar von Knoten (v,w) ist dasselbe wie die -elementige Menge von Knoten {v, w. Es muss v w sein (keine Schlingen!). Die Darstellung soll jedoch einfach bleiben. Daher werden wir sowohl für gerichtete als auch ungerichtete Kanten dieselbe Notation (v,w) verwenden. v Knoten v v Kante v v 5 V = { v, v, v, v, v 5 E = { (v,v ), (v,v ), (v,v ), (v,v ), (v,v ), (v 5,v ) Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08 -

Adjazenz und Grad Ein Knoten w ist adjazent zu (benachbart zu) einem Knoten v, falls (v,w) eine Kante des (gerichteten bzw. ungerichteten) Graphen ist. v v w w Bei einem ungerichteten Graphen ist die Adjazenzbeziehung immer symmetrisch. Bei einem gerichteten Grahen ist die Adjazenzbeziehung im allg. unsymmetrisch. Bei einer gerichteten Kante (v,w) wird w auch Nachfolger von v und v Vorgänger von w genannt. Bei einer ungerichteten Kante (v,w) heißen v und w auch Nachbarn. In einem ungerichteten Graphen ist der Grad eines Knoten die Anzahl seiner Nachbarn. Bei einem gerichteten Graphen wird die Anzahl der Vorgänger Eingangsgrad und die Anzahl der Nachfolger Ausgangsgrad genannt. v v - Der Knoten v hat 5 adjazente Knoten. - Der Grad von v ist damit 5. - Der Knoten v hat Vorgänger und Nachfolger. - Der Eingangsgrad von v ist damit und der Ausgangsgrad ist. Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08 -

Weg Ein Weg (engl. path) ist eine Folge von Knoten v, v,, v n, wobei n und (v i, v i+ ) für i < n Kanten im Graphen sind. Die Länge des Weges v, v,, v n ist gleich der Anzahl der Kanten und damit n-. n darf sein; dann hat der Weg die Länge 0. Ein Weg heißt einfacher Weg, falls alle Knoten bis auf Anfangs- und Endknoten unterschiedlich sind. v v v v v v v v 5 Ein einfacher Weg der Länge : v, v, v, v. v v 5 Ein (nicht einfacher) Weg der Länge 5: v, v, v 5, v, v, v Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-5

Zyklus Ein Weg v, v,, v n in einem gerichteten Graph heisst Zyklus (cycle), falls Anfangsknoten v und Endknoten v n identisch sind und n ist (d.h. wenigstens eine Kante). Ein Weg v, v,, v n in einem ungerichteten Graph heisst Zyklus (cycle), falls Anfangsknoten v und Endknoten v n identisch sind, n ist (d.h. wenigstens drei Kanten) und alle Kanten unterschiedlich sind. Zyklen sind einfach, wenn der Weg einfach ist. Zwei Zyklen sind gleich, falls sich ihre Wege (jeweils ohne Endknoten) durch eine zyklische Verschiebung unterscheiden. Zyklenfreie Graphen werden auch azyklisch (acyclic graph) genannt. v v v v v v v v v Ein einfacher Zyklus (in einem gerichteten Graph) der Länge : v, v, v v v 5 Ein einfacher Zyklus der Länge : v, v, v, v v v 5 Ein nicht-einfacher Zyklus der Länge 6: v, v, v, v, v 5, v, v Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-6

Teilgraph Ein Graph G' = (V', E') ist ein Teilgraph von Graph G = (V, E), falls V' Í V und E' Í E Enthält darüber hinaus G' alle Kanten aus E, die Knoten aus V' verbinden, dann heißt G' der durch V' induzierte Teilgraph von G, d.h. E' = {(u,v) Î E / u,v Î V' v 5 v v v v v v v v Graph G v v Teilgraph von G v v Der durch V = {v, v, v, v induzierte Teilgraph von G Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-7

Zusammenhang Ein ungerichteter Graph heißt zusammenhängend (connected), falls es von jedem Knoten einen Weg zu jeden anderen Knoten gibt. Eine Zusammenhangskomponente eines ungerichteten Graphen G ist ein maximal zusammenhängender Teilgraph. v Graph G = (E,V) ist zusammenhängend. Der durch V \ {v induzierte Teilgraph (d.h. G ohne Knoten v und ohne Kanten mit v als Endknoten) besteht aus genau zwei Zusammenhangskomponenten. Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-8

Strenger und schwacher Zusammenhang Ein gerichteter Graph heißt streng zusammenhängend (strongly connected), falls es von jedem Knoten einen Weg zu jedem anderen Knoten gibt. Wenn bei einem gerichteter Graph G der entsprechende ungerichtete Graph zusammenhängend ist, dann wird G auch schwach zusammenhängend genannt. (weakly connected). Gerichteter Graph, der schwach aber nicht stark zusammenhängend ist. Strenge und schwache Zusammenhangskomponenten werden analog zu Zusammenhangskomponenten bei ungerichteten Graphen definiert. Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-9

Wald und Baum Ein ungerichteter und azyklischer Graph heißt auch Wald. Ein zusammenhängender Wald heißt auch Baum. Wald Baum Ein Wurzelbaum ist ein gerichteter, azyklischer Graph, bei dem genau ein Knoten die sogenannte Wurzel den Eingangsgrad 0 hat und alle anderen Knoten den Eingangsgrad haben. Bei einer Kante (v,w) heisst v auch Elternknoten von w und w Kindknoten von v. Knoten ohne Kinder heißen auch Blätter. In der graphischen Darstellung zeigen die Kanten üblicherweise nach unten. Die im Kap. eingeführten Suchbäume sind Wurzelbäume. Wurzel w v Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-0

Gewichteter Graph Ist jeder Kante (v,w) eine reelle Zahl c(v,w) als Kosten oder Gewicht zugeordnet, spricht man von einem gewichteten Graphen. Sind darüber hinaus die Gewichte ³ 0, dann heißt der Graph auch Distanzgraph. 7 6 5 Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08 -

Teil III: Graphenalgorithmen Anwendungen Definitionen Datenstrukturen für Graphen - Adjazenzmatrix - Adjazenzliste - Kantenliste - Implementierungshinweise für Java Elementare Algorithmen Topologisches Sortieren Kürzeste Wege Minimal aufspannende Bäume Flüsse in Netzwerken Zusammenhangskomponenten Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08 -

Adjazenzmatrix für ungewichtete Graphen A[i][j] =, falls es eine Kante von v i und nach v j gibt 0 sonst v v v v v 0 v 0 v v v v [0] [] [] [] [] [0] [] [] [] [] 0 0 0 0 0 0 0 0 0 0 0 [0] [] [] [] [] [0] [] [] [] [] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 Beachte: Die Adjazenzmatrizen sind bei einem ungerichteten Graphen symmetrisch und bei einem gerichteten Graphen im allgemeinen unsymmetrisch. Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08 -

Adjazenzmatrix für gewichtete Graphen A[i][j] = c(v,w), falls es eine Kante von Knoten v nach w gibt sonst v 7 v v 7 v v 0 6 v 0 6 v - v v - v [0] [] [] [] [] [0] [] [] [] [] 7 7 6-6 - [0] [] [] [] [] [0] [] [] [] [] 7 6 - Beachte: Die Adjazenzmatrizen sind bei einem ungerichteten Graphen symmetrisch und bei einem gerichteten Graphen im allgemeinen unsymmetrisch. Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08 -

Adjazenzliste bei einem ungerichteten Graphen wird für jeden Knoten eine linear verkettete Liste mit allen Nachbarknoten (Adjazenzliste) abgespeichert. ungerichtete Kanten werden bei beiden Endknoten eingetragen. v v [0] v 0 [] [] 0 [] v v [] 0 Bei einem gerichteten Graphen werden zwei getrennte Listen verwaltet: eine Vorgänger-Liste und eine Nachfolger-Liste. Bei einem gewichteten Graphen wird noch zusätzlich das Kantengewicht eingetragen. Um die Dynamisierbarkeit der Datenstruktur zu verbessern, kann statt eines Feldes auch eine dynamische Datenstruktur wie ein binärer Suchbaum verwendet werden. Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-5

Kantenliste Speichere die Menge aller Kanten in einer sortierten Suchstruktur (sortiertes Feld oder Suchbaum). Als Ordnungsrelation auf Kanten ist eine lexikographische Ordnung naheliegend: (v, v') (w, w') falls v < w oder v = w und v' w' Beispiel: sortiertes Kanten-Feld v v v 0 i j [0] [] [] [] 0 0 0 0 v v Alle Nachbarknoten zu v sind effizient auffindbar. Bei einem ungerichten Graphen wird für eine Kante von v nach w sowohl (v,w) als auch (w,v) gespeichert. Bei einem gerichteten Graphen wird die Kantenliste in Vorgänger- und Nachfolger-Liste aufgeteilt. Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-6

Dünn- und dichtbesetzte Graphen Falls E = O( V ) (dünnbesetzter Graph; sparse graph), dann ist die Speicherung als Adjazenzliste oder Kantenliste Speicherplatz sparender und effizienter in der Laufzeit. Falls E = O( V ) (dichtbesetzter Graph; dense graph), dann ist die Speicherung als Adjazenzmatrix Speicherplatz sparender und effizienter in der Laufzeit. Vollständiger Graph (alle Knotenpaare sind durch eine Kante verbunden) ist dichtbesetzt. Es gilt: E = V *( V -)/ = O( V ). Manhattan-Graph (Graph für Mahattan mit Kreuzungen als Knoten und Strassen als Kanten) ist dünnbesetzt. Es gilt: E * V = O( V ). Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-7

Implementierungshinweise: Adjazenzmatrizen Knoten sind durchnummeriert: 0,,,..., n- Nehme Knotennummer als Index eines zweidimensionalen Felds Beispiel: ungerichteter und gewichteter Graph int n = 0; // Anzahl der Knoten double [ ][ ] adjcencymatrix = new double[n][n]; adjcencymatrix[][] =.5; // Kante von nach mit Gewicht.5 eintragen adjcencymatrix[][] =.5; // Kante von nach mit Gewicht.5 eintragen Bei ungewichteten Graphen sind Gewichte 0 oder. Bei gerichteten Graphen ist Matrix i.a. nicht symmetrisch. Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-8

Implementierungshinweise: Feld von Adjazenzlisten Knoten sind durchnummeriert: 0,,,..., n-. Beispiel: ungerichter Graph: int n = 0; // Anzahl der Knoten List<List<Integer>> adjacencylist = new ArrayList<>(n); for (int i = 0; i < n; i++) adjacencylist.add( new LinkedList<>() ); adjacencylist.get().add(); // Kante von nach eintragen adjacencylist.get().add(); // Kante von nach eintragen adjacencylist[0] [] []... [8] [9] Gewichte können bei den Knoten abgespeichert werden. Bei gerichteten Graphen werden Nachfolger und Vorgänger in separate Listen gehalten. Statt die adjazenten Knoten in Listen zu speichern, ließen sich sich auch Sets (bei ungewichteten Graphen) oder Maps (bei gewichteten Graphen) einsetzen. Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-9

Implementierungshinweise: interne Nummerierung für Graphknoten In der Praxis kommt es häufig vor, dass die Graph-Knoten nicht von 0 bis n- nummeriert sind, sondern beispielsweise als Strings gegeben sind. Stuttgart 90 km Ulm 50km München Die Schlüssel können dann mit Hilfe einer Map (TreeMap oder HashMap) in eine interne Nummerierung von 0 bis n- umgerechnet werden: - Stuttgart à 0 - Ulm à - München à Die inverse Umrechnung von interner Nummerierung in den Schlüssel lässt sich mit einem einfachen Feld realisieren: - Stuttgart ß 0 - Ulm ß - München ß Mittels der internen Nummerierung lässt sich dann eines der indizierten Zugriffsverfahren von der vorhergehenden Seite verwenden. Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-0

Implementierungshinweise: Graph als Map () Eine Map ordnet jedem Knoten eine Adjazenzliste zu. Die Adjazenzlisten sind ebenfalls Maps und ordnen jedem adjazenten Knoten ein Gewicht zu (bei ungewichteten Graphen könnten dagegen einfachheitshalber Sets verwendet werden). Knoten können vom Typ Integer (Knoten sind nummeriert) oder von einem anderen Typ sein (z.b. String). Maps können entweder HashMaps oder TreeMaps sein (siehe Beispiel nächste Seite). Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08 -

Beispiel: ungerichteter und gewichteter Graph als Map int n = 7; // Anzahl Knoten Map< Integer, Map<Integer, Double> > adjacencylist = new TreeMap<>(); for (int i = 0; i < n; i++) adjacencylist.put(i, new TreeMap<>()); adjacencylist.get().put(,.); // Kante von nach mit Gewicht. eintragen adjacencylist.get().put(,.); adjacencylist.get().put(6,.5); // Kante von nach 6 mit Gewicht.5 eintragen adjacencylist.get(6).put(,.5); adjacencylist.get().put(, 0.5); // Kante von nach mit Gewicht 0.5 eintragen adjacencylist.get().put(, 0.5);. 5 6 0.5. 0.5 6.5 0.5 Graph als TreeMap Mit Knoten als Schlüssel und Adjazenzliste als Nutzdaten Die Adjazenzlisten sind ebenfalls TreeMaps. Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08 -

Darstellung der Algorithmen in Pseudo-Code () Um einfach und von der konkreten Datenstruktur für Graphen unabhängig zu bleiben, wird bei der Formulierung der Algorithmen folgender Pseudo- Code benutzt: Ungerichtete und gerichtete Graphen: for ( jeden adjazenten Knoten w von v ) { for ( jeden Knoten v ) { for ( jede Kante (v,w) ) { Ungerichtete Graphen: for ( jeden Nachbarn w von v ) { Gerichtete Graphen: for ( jeden Nachfolger w von v ) { for ( jeden Vorgänger w von v ) { Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08 -

Darstellung der Algorithmen in Pseudo-Code () Die hier in Pseudo-Code dargestellten Schleifen lassen sich in Java mit den besprochenen Datenstrukturen (Adjazenzmatrix, Adjazenzliste und Kantenliste) einfach realisieren. Pseudo-Code: for ( jeden Knoten v ) { Java: // Map-basierte Adjazenzliste für ungewichteten Graphen: Map<Vertex, Set<Vertex>> adjacencylist = new TreeMap<>(); for (Vertex v : adjacencylist.keyset() ) {... for ( jeden Nachfolger w von v ) { // adjacencylist wie oben definiert for (Vertex w : adjacencylist.get(v) ) {... Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08 -

Darstellung der Algorithmen in Pseudo-Code () Bei der Formulierung der Algorithmen sollen auch die Datenstrukturen möglichst einfach gehalten werden. Oft muss für jeden Knoten eine Information gespeichert werden. Im Pseudo-Code werden einfachheitshalber Felder und Indizierung gewählt. Sind die Knoten durchnummeriert, dann kann der Pseudo-Code direkt in Java übernommen werden. Bei einem beliebigen Knotentyp kann eine Map gewählt werden. Pseudo-Code: int[ ] indegree;... for ( jeden Knoten v ) { indegree[v] = Anzahl der Vorgänger; if (indegree[v] == 0)... for ( jeden Nachfolger w von v ) { if (--indegree[w] == 0)... Java: Map<Vertex, Integer> indegree = new...;... for ( jeden Knoten v ) { indegree.put(v, Anzahl der Vorgänger); if (indegree.get(v) == 0)... for ( jeden Nachfolger w von v ) { indegree.put(w, indegree.get(w)-); if (indegree.get(w) == 0)... Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-5

Teil III: Graphenalgorithmen Anwendungen Definitionen Datenstrukturen für Graphen Elementare Algorithmen - Tiefensuche - Breitensuche Topologisches Sortieren Kürzeste Wege Minimal aufspannende Bäume Flüsse in Netzwerken Zusammenhangskomponenten Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-6

Rekursive Tiefensuche (depth-first search) void visitdf(vertex v, Graph g) { Set<Vertex> besucht = { ; visitdf(v, g, besucht); void visitdf(vertex v, Graph g, Set<Vertex> besucht) { besucht.add(v); // Bearbeite v: println(v); visitdf(v,g) startet von Knoten v eine Tiefensuche im Graph g. besucht ist die Menge aller bereits besuchten Knoten. Wichtig zur Vermeidung von Endlosschleifen. visitdf(v, g, besucht) besucht Knoten v im Graphen g und ist rekursiv. for ( jeden adjazenten Knoten w von v ) if (! besucht.contains(w) ) // w noch nicht besucht visitdf(w, g, besucht); Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-7

Beispiel für rekursive Tiefensuche Tiefensuche mit Start bei Knoten Aufrufstruktur Besuchsreihenfolge:, 0,,,, 5 0 0 5 0 5 die Nachbarn eines Knoten werden in lexikographischer Reihenfolge durchlaufen. Bereits besuchte Nachbarknoten sind durch eine gestrichelte Kante verbunden und gehören nicht zur Aufrufstruktur. Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-8

Tiefensuchbaum Die Aufrufstruktur bildet mit den besuchten Knoten den sogenannten Tiefensuchbaum. Aufrufstruktur Tiefensuchbaum 0 0 0 5 0 5 5 Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-9

Iterative Tiefensuche mit einem Keller void visitdf(vertex v, Graph g) { Set<Vertex> besucht = { ; visitdf(v, g, besucht); void visitdf(vertex v, Graph g, Set<Vertex> besucht) { Stack<Vertex> stk; stk.push(v); while(! stk.empty() ) { v = stk.pop(); if ( besucht.contains(v) ) continue; besucht.add(v); // Bearbeite v: println(v); for ( jeden adjazenten Knoten w von v ) if (! besucht.contains(w) ) stk.push(w); visitdf startet von Knoten v eine Tiefensuche. visitdf besucht Knoten v im Graphen g, wobei die bereits besuchten Knoten in besucht abgespeichert werden. Im Keller stk werden alle Knoten verwaltet, die als nächstes zu besuchen sind. Die Tiefensuche wird erreicht durch die LIFO- Organisation des Kellers. Um die gleiche Besuchsreihenfolge wie bei der rekursiven Funktion zu erreichen, müssen in der for- Schleife die Nachbarn in umgekehrter Reihenfolge bearbeitet werden. Beachte: Gleiche Knoten können mehrfach eingekellert werden. Das ließe sich durch eine weitere Knotenmarkierung verhindern: - nicht besucht, - nicht besucht und im Keller, - besucht. Allerdings würde sich eine andere Besuchsreihenfolge wie bei der rekursiven Funktion ergeben. Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-0

Breitensuche - Beispiel 0 0 5 ) Beginne mit Knoten. 5 ) Besuche alle Knoten, die über genau eine Kante von Knoten erreichbar sind. 0 Besuchsreihenfolge:, 0,,,, 5 5 ) Besuche alle Knoten, die über genau Kanten von Knoten erreichbar sind. Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08 -

Breitensuche (breadth-first search) mit einer Schlange void visitbf(vertex v, Graph g) { Set<Vertex> besucht = { ; visitbf(v, g, besucht); void visitbf(vertex v, Graph g, Set<Vertex> besucht) { Queue<Vertex> q; q.add(v); while(! q.empty() ) { v = q.remove(); if ( besucht.contains(v)) continue; visitbf startet von Knoten v eine Breitensuche im Graphen g. visitbf besucht Knoten v im Graphen g, wobei die bereits besuchten Knoten im Feld besucht abgespeichert werden. In der Schlange q werden alle Knoten verwaltet, die als nächstes zu besuchen sind. Die Breitensuche wird erreicht durch die FIFO- Organisation der Schlange besucht.add(v); // Bearbeite v: println(v); for ( jeden adjazenten Knoten w von v ) if (! besucht.contains(w) ) q.add(w); Beachte: Gleiche Knoten können mehrfach in die Schlange eingereiht werden. Das ließe sich durch eine weitere Knotenmarkierung verhindern: - nicht besucht, - nicht besucht und in der Schlange, - besucht. Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08 -

Tiefen- bzw. Breitensuche bei mehreren Zusammenhangskomponenten Hat ein Graph mehrere (strenge) Zusammenhangskomponenten, dann ist es nicht garantiert, dass es von jedem Knoten v einen Weg zu jedem anderen Knoten w gibt. Sollen alle Knoten besucht werden, dann muss visitdf (Tiefensuche) bzw. visitbf (Breitensuche) mehrere Male mit allen noch nicht besuchten Knoten als Startknoten aufgerufen werden. void visitallnodes() { Set<Vertex> besucht = { ; for (jeden Knoten v) if (! besucht.contains(v) ) visit(v, g, besucht); visit kann visitdf oder visitbf sein. Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08 -

Tiefensuchwald bei Tiefensuche mit mehreren Zusammenhangskomponenten Bei der Tiefensuche in einem Graphen mit mehreren Zusammenhangskomponenten entsteht dann der sogenannte Tiefensuchwald. void visitdfallnodes() { Set<Vertex> besucht; Gerichteter Graph (mit mehreren strengen Zusammenhangskomponenten): for (jeden Knoten v) if (! besucht.contains(v)) visitdf(v, g, besucht); 5 6 Tiefensuchwald (Knoten werden nach ihrer Nummerierung aufsteigend besucht): 6 5 Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08 -

Analyse Hier: Analyse der Tiefensuche über den kompletten Graphen. Bei der Breitensuche ergibt sich dieselbe Komplexität. Jeder Knoten wird genau -mal besucht. Jede Kante wird genau -mal bei ungerichteten Graphen bzw. genau -mal bei gerichteten Graphen in einer der for-schleifen besucht. Wird die Menge besucht als boolsches Feld implementiert und werden Adjazenzlisten verwendet, ist der Aufwand für den Durchlauf aller for- Schleifen höchtens O( E ). Damit ergibt sich insgesamt: T = O( V + E ) void visitdfallnodes() { Set<Vertex> besucht = { ; for (jeden Knoten v) if (! besucht.contains(v) ) visitdf(v, g, besucht); void visitdf(vertex v, Graph g, Set<Vertex> besucht) { besucht.add(v); // Bearbeite v: println(v); for ( jeden adjazenten Knoten w von v ) if (! besucht.contains(w) ) visitdf(w, g, besucht); Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-5

Teil III: Graphenalgorithmen Anwendungen Definitionen Datenstrukturen für Graphen Elementare Algorithmen Topologisches Sortieren Kürzeste Wege Minimal aufspannende Bäume Flüsse in Netzwerken Zusammenhangskomponenten Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-6

Definition topologische Sortierung Eine Folge v 0, v, v,, v n- aller Knoten eines gerichteten Graphen G heißt topologische Sortierung, falls für alle Knoten u, v folgende Bedingung gilt: falls (u,v) eine Kante in G ist, dann steht u vor v in der Folge v 0, v, v,, v n-. Beispiel: 6 7 5 topologisch sortiert: 5 6 7 Anschaulich: Unter Einhaltung der Adjazenzbeziehung lässt sich der Graph so auf eine Linie verbiegen, dass die Pfeile nur nach rechts gehen. Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-7

Eigenschaften und Anwendungen Eigenschaften: Falls der Graph einen Zyklus enthält, dann existiert keine topologische Sortierung. Falls ein Graph topologisch sortiert werden kann, dann ist im allgemeinen die topologische Sortierung nicht eindeutig. Beispiele für Anwendungen: Stelle fest, ob es eine Durchführungsreihenfolge für die Aktivitäten oder auch Prozesse in einem Vorranggraphen gibt. Prüfe, ob Vererbungsgraph oder include-graph zyklenfrei ist. Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-8

Algorithmus für topologische Sortierung topsort liefert zu einem gerichteten List<Vertex> topsort(digraph g) { Graphen g eine topologische Sortierung. List<Vertex> ts; // topologisch sortierte Folge int[ ] indegree; // Anz. noch nicht besuchter Vorgänger Queue<Vertex> q; Idee: for (jeden Knoten v) { indegree[v] = Anzahl der Vorgänger; if (indegree[v] == 0) q.add(v); while (! q.empty() ) { v = q.remove(); ts.add(v); for ( jeden Nachfolger w von v ) if (--indegree[w] == 0) q.add(w); if (ts.size()!= Anzahl Knoten in g) return null; // Graph zyklisch; else return ts; Speichere für jeden Knoten v: indegree[v] = Anzahl der noch nicht besuchten Vorgänger. Speichere alle noch nicht besuchten Knoten v, für die InDegree[v] == 0 gilt, in einer Schlange q. q enthält also alle Knoten, die als nächstes besucht werden dürfen. Besuche als nächstes den vordersten Knoten in der Schlange q und entferne ihn aus q Topologische sortierte Folge wird in Liste ts abgespeichert. Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-9

Analyse Für jeden Knoten w kann indegree[w] höchstens einmal gleich 0 werden. Damit kommen in die Queue q höchstens V Knoten. Die while-schleife läuft damit höchstens V -mal. Jede Kante wird höchstens einmal in einer der for-schleifen besucht. Verwendet man die Adjazenzlistendarstellung, ist damit der Aufwand für den Durchlauf aller for-schleifen höchtens O( E ). Damit ergibt sich mit Adjazenzlistendarstellung insgesamt: T = O( V + E ) List<Vertex> topsort(digraph g) { List<Vertex> ts; // topologisch sortierte Folge int[ ] indegree; // Anz. noch nicht besuchter Vorgänger Queue<Vertex> q; for (jeden Knoten v) { indegree[v] = Anzahl der Vorgänger; if (indegree[v] == 0) q.add(v); while (! q.empty() ) { v = q.remove(); ts.add(v); for ( jeden Nachfolger w von v ) if (--indegree[w] == 0) q.add(w); if (ts.size()!= Anzahl Knoten in g) return null; // Graph zyklisch; else return ts; Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-50

Teil III: Graphenalgorithmen Anwendungen Definitionen Datenstrukturen für Graphen Elementare Algorithmen Topologisches Sortieren Kürzeste Wege - Problemstellung - Ungewichtete Graphen und erweiterte Breitensuche - Distanzgraphen und Dijkstra-Algorithmus - Gewichtete Digraphen und Moore-Ford-Algorithmus - Netzpläne und erweiterte topologische Sortierung - Alle kürzeste Wege in gewichteten Digraphen mit Floyd-Algorithmus Minimal aufspannende Bäume Flüsse in Netzwerken Zusammenhangskomponenten Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-5

Problemstellung kürzeste Wege () Im allgemeinen gibt es zwischen zwei Knoten u und v mehrere Wege. Ein Weg von u nach v heißt kürzester Weg, falls der Weg minimale Länge hat. Weglänge bei gewichtetem Graph ist Summe der Kantengewichte. Weglänge bei ungewichtetem Graph ist Anzahl der Kanten. Die Distanz d(u,v) zwischen u und v wird als die Länge eines kürzesten Weges definiert. Falls es keinen Weg von u nach v gibt, ist d(u,v) =. 6 7 8 8 6 7 Weg von nach 7 mit Länge 5. Kürzester Weg von nach 7 mit Länge. 0 Damit ist Distanz d(,7) =. 5 Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-5

Problemstellung kürzeste Wege () Länge eines Weges muss nicht die wörtliche Bedeutung haben. Die Gewichte (Kosten) der Kanten und damit die Weglängen können in Abhängigkeit von der Anwendung ganz unterschiedliche Bedeutungen haben. Beispiele: - Streckenlänge - Zeitspannen - Kosten - Profit: Gewinn/Verlust (Gewichte können positiv und negativ sein) - Wahrscheinlichkeiten Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-5

Verschiedene Problemvarianten () Single pair shortest path: Kürzeste Wege zwischen zwei Knoten: () Single-source shortest-path problem: Kürzeste Wege zwischen einem Knoten und allen anderen Knoten () All pairs shortest path: Kürzeste Wege zwischen allen Knotenpaaren. Für Problem () kennt man keine bessere Lösung, als einen Algorithmus für Lösung () zu nehmen, der abgebrochen wird, sobald der Zielknoten erreicht wird. Problem () kann auf Problem () zurückgeführt werden. Bei dicht besetzten Graphen (d.h. viele Kanten) gibt es jedoch eine effizientere Lösung, die zudem auch negative Kantengewichte zulässt. Problemstellungen lassen sich für verschiedene Graphtypen (gerichtet oder ungerichtet, gewichtet oder ungewichtet) algorithmisch unterschiedlich lösen. Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-5

Verschiedene Algorithmen A B C D E Problemvariante Single-source shortest-path für ungewichtete Graphen Single-source shortest-path für Distanz-Graphen (nur positive Gewichte) Single-source shortest-path für gewichtete Digraphen (auch negative Gewichten) Single-source shortest-path für gewichtete, azyklische Digraphen mit einem Start- und einem Endknoten (Netzpläne) All pairs shortest path für gewichtete Digraphen (auch negative Gewichte) Algorithmus Erweiterte Breitensuche Algorithmus von Dijkstra; A*-Verfahren Algorithmus von Moore und Ford Erweiterte topologische Sortierung Algorithmus von Floyd A ist ein Spezialfall von B. Wendet man den Dijkstra-Algorithmus auf Graphen mit Kantengewichten an, ergibt sich eine Breitensuche. D ist ein Spezialfall von C. Der auf Variante D zugeschnittene Algorithmus ist jedoch wesentlich effizienter als der Algorithmus für Variante C. Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-55

Teil III: Graphenalgorithmen Anwendungen Definitionen Datenstrukturen für Graphen Elementare Algorithmen Topologisches Sortieren Kürzeste Wege - Problemstellung - Ungewichtete Graphen und erweiterte Breitensuche - Distanzgraphen und Dijkstra-Algorithmus - Gewichtete Digraphen und Moore-Ford-Algorithmus - Netzpläne und erweiterte topologische Sortierung - Alle kürzeste Wege in gewichteten Digraphen mit Floyd-Algorithmus Minimal aufspannende Bäume Flüsse in Netzwerken Zusammenhangskomponenten Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-56

Erweiterte Breitensuche Single-source shortest-path: Gesucht sind alle kürzesten Wege von einem Startknoten s zu allen anderen Knoten. Beginne bei s und durchlaufe Graph mit Breitensuche. Speichere für jeden besuchten Knoten v die Distanz d[v] zu Startknoten s. Speichere Vorgängerknoten p[v] im kürzesten Weg nach v. p stellt ein Baum mit Wurzel s dar. Der kürzeste Weg von s nach v ergibt sich in umgekehrter Reihenfolge: v, p[v], p[p[v]],, p[ p[p[v]] ] = s Beispiel: Startknoten s = 0 5 6 7 0 v 0 5 6 7 d[v] 0 5 6 5 6 p[v] - - - - 7 () () () 0 7 v 0 5 6 7 d[v] 0 p[v] - - - - - - - - v 0 5 6 7 d[v] 0 p[v] - 5 () () () Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-57

Algorithmus für erweiterte Breitensuche Eingabe: Startknoten s und ungewichteter Graph G Ausgabe: Distanzfeld d und Vorgängerfeld p void shortestpath (Vertex s, Graph G, int[ ] d, Vertex[ ] p) { for ( jeden Knoten v ) { d[v] = ; p[v] = undef; d[s] = 0; // Distanz für Startknoten 0 5 6 7 0 v 0 5 6 7 d[v] 0 p[v] - - - - - - - - Queue<Vertex> q; q.add(s); while (! q.empty() ) { v = q.remove(); for ( jeden adjazenten Knoten w von v ) { if (d[w] == ) { // w noch nicht registriert d[w] = d[v] + ; p[w] = v; q.add(w); v 0 5 6 7 5 6 d[v] 0 p[v] - - - - 7 0 v 0 5 6 7 5 6 d[v] 0 7 p[v] - 5 Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-58

Analyse der Breitensuche Für jeden Knoten w kann d[w] höchstens einmal von auf einen endlichen Wert gesetzt werden. Damit kommen in die Queue q höchstens V Knoten. Die while-schleife läuft damit höchstens V -mal. Jede Kantenrichtung wird höchstens einmal in einer der for-schleifen besucht. Verwendet man die Adjazenzlistendarstellung, ist damit der Aufwand für den Durchlauf aller for-schleifen gleich O( E ). Damit ergibt sich mit Adjazenzlistendarstellung insgesamt: T = O( V + E ) Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-59

Teil III: Graphenalgorithmen Anwendungen Definitionen Datenstrukturen für Graphen Elementare Algorithmen Topologisches Sortieren Kürzeste Wege - Problemstellung - Ungewichtete Graphen und erweiterte Breitensuche - Distanzgraphen und Dijkstra-Algorithmus - Gewichtete Digraphen und Moore-Ford-Algorithmus - Netzpläne und erweiterte topologische Sortierung - Alle kürzeste Wege in gewichteten Digraphen mit Floyd-Algorithmus Minimal aufspannende Bäume Flüsse in Netzwerken Zusammenhangskomponenten Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-60

Algorithmus von Dijkstra Idee () Single-source shortest-path: Gesucht sind alle kürzesten Wege von einem Startknoten s zu allen anderen Knoten im einem Distanz-Graphen (Gewichte müssen 0 sein). Ähnlich wie bei der Breitensuche werden alle Knoten, die als nächstes besucht werden können, in einer Liste K (Kandidatenliste) gehalten. Aus der Kandidatenliste wird immer der Knoten mit der kleinsten Distanz als nächster besucht. 6 6 0 8 7 5 7 8 v 0 5 6 7 8 d[v] 0 6 p[v] - 0 0 0 0 - - - - Kandidatenliste Bereits besucht Als nächstes wird Knoten mit Distanzwert besucht. d[v] Distanz zwischen v und Startknoten s = 0 p[v] Vorgängerknoten im kürzesten Weg nach v Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-6

Algorithmus von Dijkstra Idee () Wird ein neuer Knoten v besucht, dann kommen eventuell neue Nachbarknoten zur Kandidatenliste. Bei allen Nachbarknoten wird geprüft, ob ein Weg über v einen kürzeren Weg ergibt. 6 7 8 6 7 8 8 8 d() = 5 6 7 6 7 0 5 5 Knoten wird besucht 0 5 5 Knoten wird besucht v 0 5 6 7 8 d[v] 0 6 p[v] - 0 0 0 0 - - - - v 0 5 6 7 8 d[v] 0 5 6 p[v] - 0 0 0 - - - Knoten 5 ist zur Kandidatenliste neu dazu gekommen. Der Distanzwert von Knoten hat sich von 6 auf 5 verbessert, da der Weg über Knoten kürzer ist als der bisherige. Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-6

Algorithmus von Dijkstra void shortestpath (Vertex s, DistanzGraph G, double[ ] d, Vertex[ ] p ) { kl = { ; // leere Kandidatenliste for (jeden Knoten v) { d[v] = ; p[v] = undef; d[s] = 0; // Startknoten () kl.insert(s); while (! kl.empty() ) { () lösche Knoten v aus kl mit d[v] minimal; for ( jeden adjazenten Knoten w von v ) { if (d[w] == ) // w noch nicht besucht und nicht in Kandidatenliste () kl.insert(w); if (d[v] + c(v,w) < d[w]) { p[w] = v; () d[w] = d[v] + c(v,w); Eingabe: Startknoten s und Distanzgraph G Ausgabe: Distanzfeld d und Vorgängerfeld p In der Kandidatenliste sind alle Knoten abgespeichert, die als nächstes besucht werden können. Die Zugriffsoperationen auf die Kandidatenliste sind rot gekennzeichnet. Mögliche Implementierungen werden auf der nächsten Folie diskutiert. Distanzwert für w verbessert sich. Kürzester Weg nach w geht nun über v. Falls in Zeile () w neu in kl eingefügt wurde, wird d[w] von zu einem endlichen Wert verbessert. Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-6

Eigenschaften Die d-werte der besuchten Knoten in Zeile () sind monoton steigend. Begründung: die d-werte der anderen Kandidaten sind und bleiben d[v]. In Zeile () wird zwar für einen adjazenten Knoten w von v der d-wert verringert. Dennoch gilt d[w] d[v], da die Gewichte der Kanten c(v,w) 0 sind. while (! kl.empty() ) { () lösche Knoten v aus kl mit d[v] minimal; Knoten v wird besucht. for ( jeden adjazenten Knoten w von v ) { if (d[w] == ) // w noch nicht besucht und nicht in Kandidatenliste () kl.insert(w); if (d[v] + c(v,w) < d[w]) { p[w] = v; () d[w] = d[v] + c(v,w); Sobald ein Knoten v besucht wird (Zeile ()), ist sein kürzester Weg bekannt. Wird ein kürzester Weg von einem Startknoten s zu einem bestimmten Zielknoten z gesucht, dann kann das Verfahren abgebrochen werden, sobald v = z besucht wird. Ein Knoten wird höchstens einmal in die Prioritätsliste eingefügt. Daher kl.size() V. Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-6

Kandidatenliste als Index-Heap Analyse () Speichere Kandidaten in einem Index-Heap (siehe Kap., Prioritätslisten), wobei als Priorität der Distanzwert aus Feld d genommen wird. Ein Index-Heap bietet eine effiziente Realisierung folgender Operationen an: - insert(v, d) in O(log V ): fügt Element v mit Priorität d ein. Aufruf in () und (). - v = delmin() in O(log V ): löscht Element mit kleinster Priorität. Aufruf in (). - change(v, dneu) in O(log V ): ändert den Vorrangwert des Elements v in dneu. Aufruf in (). Analyse des Dijkstra-Algorithmus mit Kandidatenliste als Index-Heap Jede Kantenrichtung wird genau einmal in einer der for-schleifen betrachtet. Da () und () in O(log V ) geht, ist für alle for-schleifen insgesamt O( E log V ) notwendig. Hinzu kommt höchstens V -mal die Ausführung von (), was O( V log V ) bedeutet. Insgesamt: T = O( E log V ) Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-65

Analyse () Kandidatenliste als unsortiertes Feld Speichere Kandidaten in einem unsortierten Feld. Damit benötigt die Operation in Zeile () (Minimum bestimmen) O( V ) und die Operationen in (), () und () benötigen O(). Analyse des Dijkstra-Algorithmus mit Kandidatenliste als unsortiertes Feld Die while-schleife wird höchstens V -mal durchgeführt. Für () ist O( V ) notwendig. Jede Kantenrichtung wird genau einmal in einer der for-schleifen betrachtet. Da () und () in O() geht, ist für alle for-schleifen insgesamt O( E ) notwendig. Insgesamt: T = O( V ) Fazit: Ist der Graph dicht besetzt, d.h. E = O( V ), dann ist die Variante mit Kandidatenliste als unsortiertes Feld besser. Ist der Graph dünn besetzt, d.h. E = O( V ), dann ist die Variante mit Kandidatenliste als Prioritätsliste besser. Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-66

Beispiel zu Dijkstra-Algorithmus () 6 7 8 6 7 8 8 8 6 7 6 7 0 5 Knoten 0 wird besucht 0 5 5 5 v 0 5 6 7 8 d[v] 0 p[v] - - - - - - - - - 6 7 8 v 0 5 6 7 8 d[v] 0 6 p[v] - 0 0 0 0 - - - - 8 Knoten wird besucht 6 0 5 5 7 Knoten wird besucht v 0 5 6 7 8 d[v] 0 5 6 p[v] - 0 0 0 - - - Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-67

Beispiel zu Dijkstra-Algorithmus () 6 7 8 6 7 8 8 8 6 0 5 7 Knoten wird besucht 6 0 5 7 5 5 v 0 5 6 7 8 d[v] 0 5 6 p[v] - 0 0 0 - - - 6 7 8 v 0 5 6 7 8 d[v] 0 5 6 p[v] - 0 0 0 - - 8 Knoten 6 wird besucht 6 0 5 5 7 Knoten 7 wird besucht v 0 5 6 7 8 d[v] 0 5 6 p[v] - 0 0 0 6 - Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-68

Beispiel zu Dijkstra-Algorithmus () 6 7 8 8 6 0 5 5 7 Kürzeste Wege für Startknoten s = 0 sind nun bekannt für die Zielknoten:,,, 6, 7. Kürzester Weg von 0 nach 7 ist 0,, 6, 7 mit Distanz d =. v 0 5 6 7 8 d[v] 0 5 6 5 p[v] - 0 0 0 6 7 Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-69

A*-Algorithmus: Verbesserung des Dijkstra-Algorithmus Ist der kürzeste Weg zu genau einem Zielknoten z gesucht und lässt sich die Distanz von einem Knoten v zum Zielknoten z durch eine Schätzfunktion h(v,z) abschätzen, dann lässt sich der Algorithmus von Dijkstra optimieren. Statt den Knoten v mit d[v] minimal als nächstes zu besuchen zu besuchen, wird der Knoten v besucht mit d[v] + h(v,z) minimal. Damit werden Knoten v bevorzugt, die näher zum Zielknoten liegen. Sind die Knoten des Graphen Punkte in der Euklidischen Ebene und die Gewichte gleich den Euklidischen Abständen (Luftlinienabstand), dann lässt sich als Schätzfunktion h(v,z) der Euklidische Abstand zwischen v und z wählen. z s h(,z) h(,z) Wird der kürzeste Weg von s nach z gesucht, wird zuerst Knoten besucht, weil dieser näher zu z liegt. Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-70

A*- Algorithmus boolean shortestpath (Vertex s, Vertex z, DistanzGraph G, double[ ] d, Vertex[ ] p ) { kl = { ; // leere Kandidatenliste for (jeden Knoten v) { d[v] = ; p[v] = undef; d[s] = 0; // Startknoten kl.insert(s); Ausgabe: Distanzfeld d und Vorgängerfeld p Eingabe: Startknoten s, Zielknoten z und Distanzgraph G while (! kl.empty() ) { lösche Knoten v aus kl mit d[v] + h(v,z) minimal; Änderungen gegenüber if (v == z) // Zielknotenz erreicht dem Diskstra-Algorithmus return true; sind blau gekennzeichnet. for ( jeden adjazenten Knoten w von v ) { if (d[w] == ) // w noch nicht besucht und nicht in Kandidatenliste kl.insert(w); if (d[v] + c(v,w) < d[w]) { p[w] = v; d[w] = d[v] + c(v,w); return false; Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-7

Korrektheit des A*- Algorithmus Das A*-Verfahren liefert immer einen kürzesten Weg, falls der Zielknoten z erreichbar ist und die Schätzfunktion h folgende Eigenschaften erfüllt: () h ist zulässig: 0 h(u,v) d(u,v) für alle Knoten u, v (h ist positiv und unterschätzt die Distanz d) () h ist monoton: h(u,v) c(u,w) + h(w,v) für alle Knoten u, v, w v h(u,v) h(w,v) u c(u,w) w Die Euklidische Abstandsfunktion erfüllt die beiden oberen Bedingungen. Die Schätzfunktion h(u,v) = 0 erfüllt trivialerweise beide Bedingungen. Man erhält dann genau den Algorithmus von Dijkstra. In der Literatur wird die Schätzfunktion auch Heuristik genannt (Heuristik = Strategie zur Lösungssuche) Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-7

Vergleich A*- und Dijkstra-Algorithmus Dijkstra-Algorithmus A*-Algorithmus 5 7 5 7 6 s 8 z s z 6 Schätzfunktion h und Kantengewicht c sind als Euklidischer Abstand definiert. Im Beispiel wird kürzester Weg von Startknoten s nach Zielknoten z berechnet. Reihenfoge der besuchten Knoten in rot. Berechnete kürzeste Wege sind blau markiert. Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-7

Schlechtes Verhalten von A* bei Sackgassen A* geht direkt auf das Ziel z zu, läuft aber in eine Sackgasse. s z A* besucht nun einen Weg, der sich anfangs vom Ziel entfernt und daher nicht früher betrachtet wurde. s z Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-7

Teil III: Graphenalgorithmen Anwendungen Definitionen Datenstrukturen für Graphen Elementare Algorithmen Topologisches Sortieren Kürzeste Wege - Problemstellung - Ungewichtete Graphen und erweiterte Breitensuche - Distanzgraphen und Dijkstra-Algorithmus - Gewichtete Digraphen und Moore-Ford-Algorithmus - Netzpläne und erweiterte topologische Sortierung - Alle kürzeste Wege in gewichteten Digraphen mit Floyd-Algorithmus Minimal aufspannende Bäume Flüsse in Netzwerken Zusammenhangskomponenten Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-75

Graphen mit negativen Gewichten () Hat ein Graph auch negative Gewichte, dann ist die Existenz eines kürzesten Weges nicht gesichert, da Zyklen mit negativer Länge existieren können. Durch mehrfaches Ablaufen solcher Zyklen kann die Weglänge beliebig klein (negativ) werden. u - v Zyklus mit Länge = + + = - Damit kann die Weglänge von u nach v beliebig klein werden. Die Eindeutigkeit kürzester, einfacher Wege ist jedoch garantiert (d.h. Knoten dürfen nicht mehrfach auftreten). Jedoch sind bis heute hierfür keine effizienten Algorithmen bekannt. Daher: Einschränkung auf beliebig gewichtete Digraphen ohne Zyklen negativer Länge. Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-76

Graphen mit negativen Gewichten () Der Algorithmus von Dijkstra arbeitet bei Graphen mit negativ gewichteten Kanten im allgemeinen nicht korrekt: Mit Algorithmus von Dijkstra berechneter Weg mit Länge =.. 0. 0. s= 5-0 8 z=9-0 6 7 Kürzester Weg von s nach z mit Länge = -6. Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-77

Algorithmus von Moore und Ford - Idee Single-source shortest-path: Gegeben ist ein gewichteter Digraph (Gewichte können negativ sein). Gesucht sind alle kürzesten Wege zwischen einem Startknoten s und allen anderen Knoten, sofern der Graph keine negativen Zyklen enthält. Ausgangspunkt ist der Algorithmus von Dijkstra. Beim Algorithmus von Dijkstra wird jeder Knoten v höchstens einmal besucht und zwar dann, wenn der kürzeste Weg zu v bekannt ist. Kommen aber negative gewichtete Kanten vor, dann muss jeder Knoten im allgemeinen mehrere Male besucht werden und zwar immer dann, wenn sich ein noch kürzerer Weg ergibt. Die Reihenfolge, in der die Knoten besucht werden, spielt nun keine Rolle mehr. Es wird daher eine Schlange statt einer Vorrangswarteschlange gewählt. Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-78

Algorithmus von Moore und Ford void shortestpath (Vertex s, WeightedDiGraph G, double[ ] d, Vertex[ ] p) { Queue<Vertex> kl = { ; for (jeden Knoten v) { d[v] = ; p[v] = undef; d[s] = 0; // Startknoten kl.add(s); while (! kl.empty()) { v = kl.remove(); for ( jeden adjazenten Knoten w von v ) { () if (d[v] + c(v,w) < d[w]) { () p[w] = v; () d[w] = d[v] + c(v,w); () if (! kl.contains(w) ) (5) kl.add(w); Ausgabe: Distanzfeld d und Vorgängerfeld p Eingabe: Startknoten s und gewichteter und gerichteter Graph g In der Kandidatenliste sind alle Knoten abgespeichert, die als nächstes besucht werden können. Die Zugriffsoperationen auf die Kandidatenliste sind rot gekennzeichnet. Distanzwert für w verbessert sich. Kürzester Weg nach w geht nun über v. w muss evtl. nochmals besucht werden. Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-79

Beispiel zu Moore- Ford-Algorithmus s= 5 5-0 8 9-8 6 7 Nächster besuchter Knoten ist rot gekennzeichnet. v 5 6 7 8 9 d[v] 0 5 6 - - -5-6 -5 v 5 6 7 8 9 p[v] - - - - - - - - - 8 5 6 6 8 7 5 8 Kandiatenliste kl,,,, 8, 8, 5 8, 5, 6 5, 6, 9 6, 9, 8 9, 8,, 7, 7, 9 7, 9, 5 9, 5, 8 8 9 Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-80

Analyse des Moore- Ford-Algorithmus Enthält der Graph keine Zyklen mit negativer Länge, dann wird jeder Knoten maximal ( V -)-mal in die Schlange kl eingefügt (Zeile (5) im Algorithmus). (Begründung siehe [Turau]). Wird ein Knoten V -mal eingefügt, dann muss es ein Zyklus mit negativer Länge geben und es könnte im Algorithmus eine entsprechende Ausgabe erfolgen. Würde jeder Knoten genau einmal in die Schlange kl eingefügt werden, wäre der Aufwand für alle for-schleifen gerade O( E ). Denn jede Kante im Graph wird genau einmal in einer der for-schleifen betrachtetet. (Zeile (5) kl.contains(w) kann mit Hilfe eines Booleschen Felds in O() realisiert weden). Da nun aber jeder Knoten bis zu ( V -)-mal in die Schlange kl eingefügt werden kann, erhält man insgesamt: T = O( E * V ). Prof. Dr. O. Bittel, HTWG Konstanz Algorithmen und Datenstrukuren Graphenalgorithmen SS 08-8