Übersicht 5 Effiziente Repräsentation von Mengen und Relationen .... 5.6 B-Bäume, speziell (2,4)-Bäume / Externe Suche: BBaumVarianten 5.7 (Rot-Schwarz-Bäume) 5.8 Streuspeicherverfahren (Hash-Verfahren) 6. Weitere Anwendungen von Bäumen: Binäre Heaps 6.2 Suffixbäume, effiziente Suche von Zeichenketten 7. Graphen 7.1 Begriffe 7.2 Implementierungsalternativen 7.3 Graphalgorithmen: Tiefen- / Breitensuche, Kürzeste Wege, Spannende Bäume, Topologische Ordnung, ... hs / fub – alp3-25-Graph-1 1 7.0 Einführung Anwendungsbeispiel "Routenplaner" Anwendung hs / fub – alp3-25-Graph-1 2 1 Routenplaner Graph 1 3 2 1 2 4 3 4 5 5 Modellierung mit Graphen: Ampelschaltung D E A A G C F B E D B C G F "Konfliktgraph" Suche Färbung mit minimaler Anzahl von Farben so, dass Nachbarn nie gleichfarbig. hs / fub – alp3-25-Graph-1 4 2 Modellierung mit Graphen Semantik der Kanten problemabhängig a Entfernung a in Konflikt zu b a vor b b Kapazität a wartet auf b ...... Anwendungen -> Modellieren -> Algorithmen im Modell -> Anwendungen hs / fub – alp3-25-Graph-1 5 7 Graphen 7.1 Terminologie (teilweise Wiederholung, siehe alp3-11-Tree-1 und Cormen et al.) G = (V, E) V: Knotenmenge (vertices, nodes) E: Kantenmenge ⊆ V X V (edges) Gerichteter Graph Kanten besitzen Richtung oder E ⊆ { {x,y} | x,y ∈ V} Ungerichteter Graph Schreibweise für Kanten meist gleich: (x,y) Gerichtet / ungerichtet geht aus dem Kontext hervor Weg (Pfad) der Länge n von a nach b: (x0,x2,....xn-1,xn) = (a -> b) xi ∈ V, x0 = a, xn = b (für ungerichtete auch Schreibweise (a – b)) Zyklus: Weg von Knoten x nach x in gerichteten Graphen Zyklen der Länge 1 möglich: (a->a) hs / fub – alp3-25-Graph-1 6 3 Graphen Begriffe... Zyklenfrei (kreisfrei): es gibt keine Zyklen a b zykelfrei! c G zusammenhängend: G ungerichtet und für alle a,b ∈ V gibt es Weg von a nach b. G gerichtet, stark zusammenhängend: für alle a, b ∈ V gibt es Weg von a nach b und von b nach a Spezialfall: gerichteter, zyklenfreier Graph DAG (directed acyclic graph) hs / fub – alp3-25-Graph-1 7 Graphen Begriffe Wald (forest): azyklischer, ungerichteter Graph zur Erinnerung: freier Baum :azyklischer, ungerichteter und zusammenhängender Graph hs / fub – alp3-25-Graph-1 8 4 Graphen Begriffe... G' = (V', E') Teilgraph von G = (V,E), wenn V'⊆ V und E' ⊆ E, von V' induzierter Teilgraph (V', E') mit E' = { (x,y) | x e V' und y e V'} Meist ist mit "Teilgraph" der induzierte Teilgraph gemeint. Zusammenhangskomponente (V',E') des ungerichteten Graphen G = (V,E): (Induzierter) Teilgraph von ungerichtetem Graph, der zusammenhängend ist. Starke Zusammenhangskomponente (V', E') des gerichteten Graphen (V,E): ein (von V' induzierter) stark zusammenhängender Graph. hs / fub – alp3-25-Graph-1 9 ´Graphen Begriffe... Spannender Baum G' = (V, E') des ungerichteten Graphen G = (V, E) E' : kleinste Teilmenge von E so dass: es gibt Weg (a -> b) in G => es gibt (ggf. anderen ) Weg (a -> b) in G' A Z Z A hs / fub – alp3-25-Graph-1 10 5 Graphen Begriffe... Ungerichteter Graph heißt bipartite, wenn V sich in zwei disjunkte Teilmengen V', V'' zerlegen lässt, so dass gilt: (x,y) ∈ E => x∈ V' und y ∈ V'' oder x ∈ V'' und y∈ V'. V' V'' Ungerichteter Graph heißt zweifach zusammenhängend (2-zusammenhängend, biconnected), wenn V nach Entfernen einer Kante immer noch zusammenhängend ist. hs / fub – alp3-25-Graph-1 11 Beispiel: Zusammenhang in Graphen 1 3 2 4 schnipp... 5 7 8 6 ökonomischer und redundant! hs / fub – alp3-25-Graph-1 12 6 Graphen Begriffe... Grad eines Knotens a Graphen): (in ungerichteten Anzahl der "mit a inzidenten Kanten" (der Kanten, deren einer Endpunkt a ist) Innengrad (in-degree) eines Knotens a in gerichtetem Graph: in-degree(x) = | {x | es gibt y e V (y,x) e E}| (Anzahl der Kanten, die x verlassen.) Außengrad (out-degree) eines gerichteten Graphen: out-degree(x) = | {x | es gibt y e V (x,y) e E}| (Anzahl Kanten, die in x hineinführen.) hs / fub – alp3-25-Graph-1 13 Graphen Gewichtete Graphen ... besitzen eine Kantenmarkierung w: V -> Num (Num oft ganze oder reele Zahlen) Kantengewicht kann z.B. Entfernung, Leitungskapazität, Zeitdauer,... ausdrücken. 18 A 17 10 10 20 Z 15 10 26 hs / fub – alp3-25-Graph-1 14 7 Anwendung von Graphen Graphen zur Modellierung Straßentopologie: Finde den kürzesten Weg von a nach b. Vernetzung: finde eine möglichst billiges Netz (einen zusammenhängenden Graphen mit möglichst wenigen(?) Kanten) Spiele: Labyrinth etc. Netzplan von Aktivitäten. .... und viele mehr. hs / fub – alp3-25-Graph-1 15 Anwendung von Graphen ... in der Informatik Speicherbereinigung (garbage collection) Verklemmungsauflösung Verklemmung (deadlock): - n > 1 unabhängige Akteure a, b, c,.. ("Prozesse", "Threads") benötigen knappe Betriebsmittel X, Y, Z ...(Speicher, Daten, CPU...). - Betriebsmittel werden exklusiv belegt. - .. werden freigegeben, wenn nicht mehr benötigt, aber nicht eher - Prozesse warten auf Betriebsmittel, wenn (noch) nicht frei. - es gibt eine zyklische Wartesituation. hs / fub – alp3-25-Graph-1 16 8 Anwendung: Auflösung von Verklemmungen Erkennung von Verklemmung: Zyklus in Wartegraph finden c a b d zum Beispiel: - d benötigt die von c benutzte Datei X - c wartet auf das Freigabe einer gemeinsam mit b genutzten Warteschlange. - b wartet auf die von d exklusiv geöffnete Protokolldatei. oft kein Programmierfehler, sondern Situation, die dynamisch entstehen kann. systematische Behandlung in ALP 4 – Nichtsequentielle Programmierung hs / fub – alp3-25-Graph-1 17 Graphen Typische Algorithmen alle Knoten durchlaufen. - Breitensuche ("erst alle Nachbarn") - Tiefensuche ("Pfad so lange wie möglich verlängern") Weg von a nach b finden (evtl. kürzesten). Alle kürzesten Wege von a zu beliebigem anderen Knoten. Zyklen finden. Minimalen spannenden Baum finden. d.i. ein Graph, der keine "überflüssigen" Kanten enthält und minimale Summe der Kantengwichte hat. Maximaler Fluss (z.B. Verkehrsfluss) zwischen 2 Knoten. Laufzeit? abhängig von .... Implementierung Teils nur für gerichtete Graphen wohldefiniert. hs / fub – alp3-25-Graph-1 18 9 Graphen 7.2 Implementierungsvarianten Ungewöhnliche Implementierung: Externspeicherrelationen intern entspräche das einer "Kantenliste". R = { (x,y,w) | (x,y) ∈ V(G) mit Kantengewicht w} "Finde alle Pfade der Länge 2 mit S T w Anfangspunkt x und Kantengewichten w, w' < 5 " .... ...... ... x y 4 .... ... ... Mit "Zugriffspfad" für Attribut S - z.B. Hash oder B-Baum, S als Schlüssel – lässt sich das selbst für sehr große Graphen effizient realisieren. Bsp: Positionierungssysteme mit Straßentopologie hs / fub – alp3-25-Graph-1 19 GraphGraph-Implementierung Adjazenzliste a x b a c c b public class Graph { class Edge {// only destination req. ...} private Hashtable nodeLabels; private Vector nodes; .... } c x x y y b a c x oft verwendete interne Graphrepräsentation y hs / fub – alp3-25-Graph-1 20 10 GraphGraph-Implementierung Adjazenzmatrix int V = 100; // 100 Knoten boolean a[][] = new boolean [V][V]; a[i][j] = 1 genau dann wenn es Kante von i nach j gibt Ungerichteter Graph: Diagonalmatrix reicht wegen Symmetrie b a b c x y a a 0 0 0 1 0 b 1 0 1 0 0 c 0 1 0 1 1 x x 1 1 1 1 1 y 0 0 0 0 0 c y hs / fub – alp3-25-Graph-1 21 Graphimplementierung Objektorientiert als Geflecht interface Vertex { // Constructor creates a node void setLabel(Object n); // labels node Object getLabel(); // label of node void connect(Vertex v); // creates edge to node v Iterator findNeighbours(); // return Iterator on Neighbors Set reachable(); // delivers all reachable nodes ... } hs / fub – alp3-25-Graph-1 22 11 Graphimplementierung ... als Geflecht von Knoten public class VertexLkd implements Vertex { public VertexLkd () { name = null; } // name = key public VertexLkd (Object n) { name = n; } // data fields public final Object name; protected Set edges = new LinkedList(); // assumed that LinkedList implements iterator // operations public void connect (Vertex v) { edges.addElement (v); } public Object getLabel() {return name;} public Iterator findNeighbours() {return edges.iterator();} public Set reachable() {.....} } hs / fub – alp3-25-Graph-1 23 Graphimplementierung ... oder als Adjazenzliste mit Knoten-Hashtabelle public class Graph { protected java.util.HashTable ht = new HashTable(); public addVertex (Object name) { ht.put(name, new VertexLkd(name); } public boolean connected(Object name1,Object name2) throws NotFoundException { return ((Vertex)ht.get(name1)).connected( ht.get(name2)); } public void traverseDFS(){....// uses findNeighbours...} public void traversBFS() {....} // more algorithms on graphs ... } hs / fub – alp3-25-Graph-1 24 12 7.3 Graphalgorithmen 7.3.1 Knotentraversierung: Tiefensuche Ziel: alle Knoten systematisch durchlaufen zwei Basisalgorithmen: 2 " Breitensuche: erst die Nachbarn des Startknotens, dann rekursiv die Nachbarn der Nachbarn" 1 3 4 5 " Tiefensuche: 6 verfolge Pfad so lange. bis ein schon durchlaufener Knoten getroffen wird, dann Backtrack" Breitensuche Schwierigkeit: Organisation der schon durchlaufenden Knoten. hs / fub – alp3-25-Graph-1 25 Graphalgorithmen: Tiefensuche ("depth ("depth first search") search") Prinzip: verlängere aktuellen Pfad bis keine Verlängerung mehr möglich. Backtrack zum letzten Knoten, der Alternative (ausgehende Kante, die noch nicht durchlaufen wurde) hat. gray black 1 1,2 1,2,3 1,2,3,5 1,2,3,5,4 4 1,2,3,5 4 1,2,3,5,6 1,2,3,5 4,6 1,2 4,6,5,3 1 4,6,5,3,2 4,6,5,3,2,1 I 2 II 1 V 4 3 IV III 5 VII VI 6 Backtrack-Implementierung am einfachsten implizit mit Rekursionsstapel (stack) hs / fub – alp3-25-Graph-1 26 13 Graphalgorithmen: Tiefensuche Baumdarstellung 1 (Beispiel) I VIII 2 4 II 3 III Jede Kante einmal durchlaufen 5 VI IV 6 4 V 2 VII 4 hs / fub – alp3-25-Graph-1 27 Tiefensuche Modifiziertes Beispiel: void dfsVisitNode(node s) { s.colour = grey; for all x=nachfolger(s) { if(x.colour = white) { x.previous = s; x.colour = gray; x.doSomething; dfsVisitNode(s); } x.colour = black; } } 2 1 III 4 3 IV 5 II I 6 Falsch: Nur korrekt, wenn Graph stark zusammenhängend! s=5 : Nur 5,6,4,2 werden traversiert. Allgemein entsteht Wald von Bäumen. hs / fub – alp3-25-Graph-1 28 14 Tiefensuche V void dfs( ) { // requires: all nodes white 1 for all nodes s VI 4 if (s.color = white) (ii) dfsVisitNode(s); } Beispiel: Reihenfolge s= 5,1,2,3,4,6 2 III 3 IV 5 II 2 V 1 III 4 3 1 IV 4 VII 3 IV (iîi) I II III VI 5 (i) 2 I 6 VIII 5 II 6 6 hs / fub – alp3-25-Graph-1 I 29 Laufzeit Tiefensuche Laufzeit Adjazenzlisten-Repräsentation for all nodes s if (s.color = white) dfsVisitNode(s) for all x=nachfolger(s) { if(x.colour = white) { x.previous = s; x.colour = gray; x.doSomething; dfsVisitNode(s); } Insgesamt: O(V) + O(V) Aufrufe O(|Nachfolger(s)| Σ |Nachfolger(s)| = O(V+E) s∈V hs / fub – alp3-25-Graph-1 30 15 Graphalgorithmen: Breitensuche 2 1 Annahme: ungerichteter zusammenhängender Baum Queue q; 4 void bfs (Node s); s.colour=grey; wListe.enqueue(s); while (!wListe.empty()) { x = q.dequeue(); for each nachfolger(x) { if (x.colour = white) { x.colour = gray; doSomethingWith(x); q.enqueue(x); } } u.colour = black; q.enqueue(u); 3 5 6 x 1 1 1 2 2 4 4 3 5 6 - 6 q 2 2,4 4 4,3 3,5 3,5,6 5,6 6 - - black 1 1 1,2 1,2 1,2,4 1,2,4,3 1,2,4,3,5 1,2,4,3,5,6 7.3.2 Breitensuche Ergänzung: für jeden Knoten x ist der Vorgänger (Nachbarknoten), y von dem x zum erstenmal (x.color = white) erreicht wurde, eindeutig. ..... if (x.colour = white) { x.previous = u; x.colour = gray; doSomethingWith(x); q.enqueue(x); } Es gilt: Weg von s nach x ist (kanten-)minimal.... ..... denn alle Knoten der Entfernung i vom Startknoten x werden vor denen der Entfernung i + 1 besucht. hs / fub – alp3-25-Graph-1 32 16 Baumdarstellung von Graphsuchproblemen 1 2 3 5 4 4 2 2 5 6 6 Alle Kanten markieren, die zu weißen (noch nicht besuchten) Knoten führen -> spannender Baum hs / fub – alp3-25-Graph-1 33 Breitensuche und Spannender Baum Spannender Baum S(G)von G: Kanten so entfernen, dass b von a in S erreichbar gdw in G erreichbar und S hat minimale Kantenzahl 2 1 3 4 Verfahren liefert spannenden Baum: 5 ungerichtet: klar, Wurzelpfad von Knoten bis zur Wurzel verfolgen und von der Wurzel bis zum Zielknoten. gerichtet: nur wenn stark zusammenhängend. 6 Frage: Minimal bei Kantengewicht w(k) != 1 für alle Kanten k? Sicher nicht! hs / fub – alp3-25-Graph-1 34 17 Laufzeit Breitensuche Laufzeit: Adjazenzlisten-Repräsenation while (!wListe.empty()) { x = q.dequeue(); for each nachfolger(x) {..... Jeder Knoten wird nur einmal auf Warteliste gesetzt : O(V) ... und nur einmal entfernt. Dabei Traversierung aller Nachfolger => Adjazenzliste wird nur einmal traversiert => insgesamt O(E) Operationen auf Kanten Laufzeit: O(E + V) mit E, V sind hier jeweils die Anzahlen |E|, |V| gemeint hs / fub – alp3-25-Graph-1 35 18