Grundlagen der Algorithmen und Datenstrukturen Kapitel 8 Christian Scheideler + Helmut Seidl SS 2009 12.06.09 Kapitel 8 1 Graphen Graph G=(V,E) besteht aus • Knotenmenge V • Kantenmenge E ungerichteter Graph 12.06.09 gerichteter Graph Kapitel 8 2 Graphen • Ungerichteter Graph: Kante repräsentiert durch Teilmenge {v,w} ½ V • Gerichteter Graph: Kante repräsentiert duch Paar (v,w) 2 V£ V (bedeutet v w) ungerichteter Graph 12.06.09 Kapitel 8 gerichteter Graph 3 Graphen Anwendungen: • Ungerichtete Graphen: Symmetrische Beziehungen jeglicher Art (z.B. {v,w} 2 E genau dann, wenn Distanz zwischen v und w maximal 1 km) • Gerichtete Graphen: asymmetrische Beziehungen (z.B. (v,w) 2 E genau dann, wenn Person v Person w mag) 12.06.09 Kapitel 8 4 Graphen Im folgenden: nur gerichtete Graphen. Modellierung eines ungerichteten Graphen als gerichteter Graph: Ungerichtete Kante ersetzt durch zwei gerichtete Kanten. • n: aktuelle Anzahl Knoten • m: aktuelle Anzahl Kanten 12.06.09 Kapitel 8 5 Operationen auf Graphen G=(V,E): Graph-Variable • Node: DS für Knoten, Edge: DS für Kanten Operationen: • G.insert(Edge e): E=E [ {e}; • G.remove(Key i, Key j): E=En{e}; für die Kante e=(v,w) mit Key(v)=i und Key(w)=j • G.insert(Node v): V=V [ {v}; • G.remove(Key i): sei v2V der Knoten mit Key(v)=i. V:=Vn{v}, E:=En{(x,y) | x=v _ y=v} • G.find(Key i): gib Knoten v aus mit Key(v)=i • G.find(Key i, Key j): gib Kante (v,w) aus mit Key(v)=i und Key(w)=j 12.06.09 Kapitel 8 6 Operationen auf Graphen Anzahl der Knoten oft fest. In diesem Fall: • V={0,…,n-1} (Knoten hintereinander nummeriert, identifiziert durch ihre Keys) Relevante Operationen: • G.insert(Edge e): E=E [ {e}; • G.remove(Key i, Key j): E=En{e}; für die Kante e=(i,j) • G.find(Key i, Key j): gib Kante e=(i,j) aus 12.06.09 Kapitel 8 7 Operationen auf Graphen Anzahl der Knoten variabel: • Hashing kann verwendet werden, um Keys von n Knoten in den Bereich {0, …,O(n)} zu hashen. • Damit kann variabler Fall auf den Fall einer statischen Knotenmenge reduziert werden. (Nur O(1)-Vergrößerung gegenüber statischer Datenstruktur) 12.06.09 Kapitel 8 8 Operationen auf Graphen Im folgenden: Konzentration auf statische Anzahl an Knoten. Parameter für Laufzeitanalyse: • n: Anzahl Knoten • m: Anzahl Kanten • d: maximaler Knotengrad (maximale Anzahl ausgehender Kanten von Knoten) 12.06.09 Kapitel 8 9 Graphrepräsentationen Kapitel 8.1: Sequenz von Kanten (0,1) 12.06.09 (1,2) 0 1 3 2 (2,3) Kapitel 8 (3,0) null 10 Sequenz von Kanten (0,1) (1,2) (2,3) (3,0) null Zeitaufwand: • G.find(Key i, Key j): Θ (m) im worst case • G.insert(Edge e): O(1) • G.remove(Key i, Key j): Θ (m) im worst case 12.06.09 Kapitel 8 11 Graphrepräsentationen Kapitel 8.2: Adjazenzfeld n-1 0 0 3 1 V 0 2 4 5 offsets in E E 1 2 2 3 3 2 0 (0,1),(0,2) 0 m-1 (2,3) Hier: nur Zielkeys in echter DS Edge [] E; 12.06.09 Kapitel 8 12 Adjazenzfeld 0 1 3 2 V 0 2 4 5 offsets in E E 1 2 2 3 3 0 Zeitaufwand: • G.find(Key i, Key j): Zeit O(d) • G.insert(Edge e): Zeit O(m) (worst case) • G.remove(Key i, Key j): Zeit O(m) (worst case) 12.06.09 Kapitel 8 13 Graphrepräsentationen Kapitel 8.3: Adjazenzliste 0 0 1 n-1 V 3 2 1 2 2 3 3 0 Hier: nur Zielkeys In echter DS: DList<Edge> [] V; 12.06.09 Kapitel 8 14 Adjazenzliste 0 3 V 1 2 1 2 2 3 3 0 Zeitaufwand: • G.find(Key i, Key j): Zeit O(d) Problem: d kann • G.insert(Edge e): Zeit O(d) groß sein! • G.remove(Key i, Key j): Zeit O(d) 12.06.09 Kapitel 8 15 Graphrepräsentationen Kapitel 8.4: Adjazenzmatrix 0 0 1 1 0 1 A= 0 0 1 1 0 0 0 1 3 2 1 0 0 0 • A[i][j] 2 {0,1} (bzw. Zeiger auf Edge) • A[i][j]=1 genau dann, wenn (i,j) 2 E 12.06.09 Kapitel 8 16 Adjazenzmatrix 0 0 1 1 0 1 A= 0 0 1 1 0 0 0 1 3 2 1 0 0 0 Zeitaufwand: • G.find(Key i, Key j): Zeit O(1) Aber: Speicher• G.insert(Edge e): Zeit O(1) aufwand O(n2) • G.remove(Key i, Key j): Zeit O(1) 12.06.09 Kapitel 8 17 Graphrepräsentationen Besser: Adjazenzliste + Hashtabelle 0 e1 e2 1 e4 e6 3 V e5 e3 2 0,1 e1 e3 e2 e4 0,2 1,2 e5 1,3 e6 2,3 3,0 Hashtabelle 12.06.09 Kapitel 8 18 Adjazenzliste+Hashtabelle Zeitaufwand: • G.find(Key i, Key j): O(1) (worst case) • G.insert(Edge e): O(1) (im Mittel) • G.remove(Key i, Key j): 0,1 O(1) (im Mittel) • Speicher: O(n+m) 12.06.09 Kapitel 8 V e1 e3 e2 e4 0,2 1,2 e5 1,3 e6 2,3 3,0 19 Graphrepräsentationen Kapitel 8.5: Implizite Repräsentationen (k,l)-Gitter G=(V,E): • V=[k]£ [l] ([a]={0,…,a-1} für a2IN) • E={((v,w),(x,y)) | (v=x ^ |w-y|=1) _ (w=y ^ |v-x|=1)} Beispiel: (5,4)-Gitter 12.06.09 Kapitel 8 20 Graphrepräsentationen Kapitel 8.5: Implizite Repräsentationen (k,l)-Gitter G=(V,E): • V=[k]£ [l] ([a]={0,…,a-1} für a2IN) • E={((v,w),(x,y)) | (v=x ^ |w-y|=1) _ (w=y) ^ |v-x|=1)} • Speicheraufwand: O(log k + log l) (speichere Kantenregel sowie k und l) • Find-Operation: O(1) Zeit (reine Rechnung) 12.06.09 Kapitel 8 21 Zusammenfassung Verschiedene Graphrepräsentationen: • Kantenliste • Adjazenzfeld • Adjazenzliste • Adjazenzmatrix • Adjazenzliste + Hashtabelle • Implizite Graphrepräsentation Weiter mit Graphdurchlauf (Kapitel 9) 12.06.09 Kapitel 8 22