Kap. 8: Repräsentation von Graphen Einleitung I 1736 stellt L. Euler die folgende “touristische” Frage: I Straßen- oder Computernetzwerke I Zugverbindungen (Raum und Zeit) I Soziale Netzwerke (Freundschafts-, Zitier-, Empfehlungs-,. . . ) I Aufgabenabhängigkeiten Scheduling-Probleme I Werte und arithmetische Operationen Compilerbau I ... 303 Repräsentation von Graphen self−loop s 1 z I Was zählt, sind die Operationen! I Eine triviale Repräsentation: I Felder I Verkettete Listen I Matrizen I Implizit I Diskussion 2 H w 1 2 y 1 −2 w 1 v t 1 1 1 1 x 2 1 v u G u w s v K5 x t U u w K3,3 u v undirected w v bidirected 304 Notation und Konventionen I I I I I Graph G = ( |{z} V , |{z} E ): Knoten Kanten n = |V | m = |E | Knoten: s, t, u, v , w , x, y , z Kanten e 2 E . Oder: Knotenpaare (manchmal Knotenmengen der Größe 2) 305 Notation und Konventionen I I I I I Graph G = ( |{z} V , |{z} E ): Knoten Kanten n = |V | m = |E | Knoten: s, t, u, v , w , x, y , z Kanten e 2 E . Oder: Knotenpaare (manchmal Knotenmengen der Größe 2) WICHTIG: Buchstabenzuordnungen sind unverbindliche Konvention I Manchmal werden ganz andere Buchstaben verwendet. I Im Zweifel immer genau sagen, was was ist. Das gilt für die ganze theoretische Informatik! 305 Ungerichtete ! gerichtete Graphen Meist repräsentieren wir ungerichtete Graphen durch doppelt gerichtete Graphen wir konzentrieren uns auf gerichtete Graphen 2 1 2 3 4 1 3 4 306 Operationen Ziel: O(Ausgabegröße) für alle Operationen Grundoperationen: I I Statische Graphen: Konstruktion, Konversion und Ausgabe (O(m + n) Zeit) Navigation: Gegeben v , finde ausgehende Kanten. Dynamische Graphen: Knoten/Kanten einfügen/löschen s y t z v w x u 307 Weitere Operationen s t 1 I Zugriff auf assoziierte Information I Mehr Navigation: Finde eingehende Kanten I Kantenanfragen: (z, x) 2 E ? z 7 6 5 w 8 y 4 2 v ? 3 6 4 3 x 5 u 308 Kantenfolgenrepräsentation Folge von Knotenpaaren (oder Tripel mit Kantengewicht) + kompakt + gut für I/O Fast keine nützlichen Operationen – außer alle Kanten zu durchlaufen Beispiele: Übung: isolierte Knoten suchen, Kruskals MST-Algorithmus (später), Konvertierung. u =s w , h(u, v ), (v , w ), (w , u), (u, w )i v 309 Adjazenzfelder I V = 1..n oder 0..n 1 I Kantenfeld E speichert Ziele und zwar gruppiert nach Startknoten I V speichert Index der ersten ausgehenden Kante I Dummy-Eintrag V [n + 1] speichert m + 1 2 1 4 1 V 1 E 2 1 3 n 5 7 5=n+1 7 3 3 2 4 4 m 7=m+1 3 Beispiel: Ausgangsgrad(v ) = V[v + 1] V[v ] 310 Kantenliste ! Adjazenzfeld Zur Erinnerung: KSort (BucketSort) Function adjacencyArray(EdgeList) V=h1, 0, . . . , 0i : Array [1..n + 1] of N foreach (u, v ) 2 EdgeList do V [u]++ for v := 2 to n + 1 do V [v ] += V [v 1] foreach (u, v ) 2 EdgeList do E [ V [u]] = v return (V , E ) // count // prefix sums // place 2 1 4 1 V 1 E 2 1 3 n 5 7 5=n+1 7 3 3 2 4 4 m 7=m+1 3 311 Beispiel 1 V 1 0 2 1 4 3 n 0 0 3 2 2 3 5 7 V 1 3 5 5=n+1 0 count 0 0 prefix sum 7 7 distribute 7 7 E 2 3 1 3 4 2 4 m 7=m+1 312 Operationen für Adjanzenzfelder I Navigation: einfach I Kantengewichte: E wird Feld von Records (oder mehrere Felder) I Knoteninfos: V wird Feld von Records (oder mehrere Felder) 2 a 1 d 4 e c b f 3 1 V 1 E 2 1 w a 3 n 5 7 5=n+1 7 3 3 2 b c 4 d 4 m e f 7=m+1 313 Operationen für Adjanzenzfelder I Navigation: einfach I Kantengewichte: E wird Feld von Records (oder mehrere Felder) I Knoteninfos: V wird Feld von Records (oder mehrere Felder) I Eingehende Kanten: umgedrehten Graphen speichern I Kanten löschen: explizite Endindizes I Batched Updates: neu aufbauen 2 a 1 d 4 e c b f 3 1 V 1 E 2 1 w a 3 n 5 7 5=n+1 7 3 3 2 b c 4 d 4 m e f 7=m+1 313 Kantenanfragen Hashtabelle HE speichert (ggf. zusätzlich) alle Kanten. Unabhängig von der sonstigen Graphrepräsentation 314 Adjazenzlisten speichere (doppelt) verkettete Liste adjazenter Kanten für jeden Knoten. + einfaches Einfügen von Kanten + einfaches Löschen von Kanten (ordnungserhaltend) mehr Platz (bis zu Faktor 3) als Adjazenzfelder mehr Cache-Misses 1 1 n 2 1 2 1 4 3 4 2 n 2 1 3 4 2 4 1 3 4 2 4 1 2 3 m 1 4 3 315 Adjazenzlisten aufrüsten I Knotenlisten für Knotenupdates I Eingehende Kanten I Kantenobjekte (in globaler Kantenliste) I Zeiger auf Umkehrkante 1 0 E list (0,1) (0,2) out list in list 0 0 (1,3) 0 2 V list first first deg deg out in out in 0 0 0 0 (2,1) (2,3) 0 0 0 (1,2) rev from to 0 0 0 0 0 0 3 0 2 0 0 2 2 1 2 2 2 0 2 3 0 316