10.1 Implementierung eines gewichteten Graphen 10.2 Implementierung der Breitensuche 10.3 Implementierung der Tiefensuche 10 147
Teil X Graphalgorithmen in Java Überblick Implementierung eines gewichteten Graphen Implementierung der Breitensuche Implementierung der Tiefensuche Saake/Schallehn Algorithmen & Datenstrukturen II 10 1 Implementierung eines gewichteten Graphen Grundprinzip: Adjazenzliste (Angepasste) Implementierung aus Buch Durch Adjazenliste keine Knoten-Klasse erforderlich Benannte Knoten für eindeutigen Zugriff Wichtung von Kanten erfordert extra Kantenklasse Umgegestellt auf Java Generics Bugfixes ;-) Original-Code: siehe Buch bzw. zugehörige Web-Seite Angepasster Code: auf Web-Seite zur Vorlesung Saake/Schallehn Algorithmen & Datenstrukturen II 10 2 148 Uni Magdeburg, WS 2005/06
Graphen-Klasse labels für Zugriff auf Knoten nach Namen nodes implementiert Adjazenliste als Liste von Liste von Kanten public class WeightedGraph { private HashMap<String,Integer> labels; private List<List<Edge> > nodes; Saake/Schallehn Algorithmen & Datenstrukturen II 10 3 10 Graphen-Klasse /2 public void addnode(string label) { if (labels.containskey(label)) throw new NodeAlreadyDefinedException(); nodes.add(new ArrayList<Edge>()); int idx = nodes.size() - 1; labels.put(label, new Integer(idx)); Saake/Schallehn Algorithmen & Datenstrukturen II 10 4 Graphen-Klasse /3 public void addedge(string src, String dest, int cost) { adjlist = nodes.get(getnodeid (src)); adjlist.add ( new Edge (getnodeid(dest), cost)); Saake/Schallehn Algorithmen & Datenstrukturen II 10 5 Uni Magdeburg, WS 2005/06 149
Graphen-Klasse /4 public int getnodeid(string label) { Integer i = labels.get(label); if (i == null) throw new NoSuchElementException(); return i.intvalue(); Saake/Schallehn Algorithmen & Datenstrukturen II 10 6 Kanten-Klasse Speicherung der Zuordnung von Gewichten zu Zielknoten static class Edge { int dest, cost; public Edge(int d, int c) { dest = d; cost = c; Saake/Schallehn Algorithmen & Datenstrukturen II 10 7 Testrahmen: ungerichteter Graph public static void main(string[] args) { WeightedGraph g1 = new WeightedGraph(); g1.addnode( r ); g1.addnode( s ); g1.addnode( t ); g1.addnode( u ); g1.addnode( v ); g1.addnode( w ); g1.addnode( x ); g1.addnode( y ); g1.addedge( s, r, 1); g1.addedge("r", ß", 1); g1.addedge( r, v, 1); g1.addedge("v", "r", 1); g1.addedge( s, w, 1); g1.addedge("w", ß", 1); g1.addedge( w, t, 1); g1.addedge("t", "w", 1); g1.addedge( w, x, 1); g1.addedge("x", "w", 1); g1.addedge( t, u, 1); g1.addedge(ü", "t", 1); g1.addedge( t, x, 1); g1.addedge("x", "t", 1); g1.addedge( u, y, 1); g1.addedge("y", u, 1); g1.addedge( x, y, 1); g1.addedge("y", "x", 1); System.out.println(g1); Saake/Schallehn Algorithmen & Datenstrukturen II 10 8 150 Uni Magdeburg, WS 2005/06
Testrahmen: gerichteter Graph WeightedGraph g2 = new WeightedGraph(); g2.addnode( u ); g2.addnode( v ); g2.addnode( w ); g2.addnode( x ); g2.addnode( y ); g2.addnode( z ); g2.addedge( u, v, 1); g2.addedge( u, "x", 1); g2.addedge( x, v, 1); g2.addedge("v", "y", 1); g2.addedge( y, x, 1); g2.addedge("w", "y", 1); g2.addedge( z, z, 1); g2.addedge("w", ß", 1); g2.searchdepthfirst(); Saake/Schallehn Algorithmen & Datenstrukturen II 10 9 10 Implementierung der Breitensuche BFS = BreadthFirstSearch Implementierung als iterativer Algorithmus Konstanten für Farbmarkierungen KlasseBFSItem für Traversierungszustände einzelner Knoten Algorithmus unter Verwendung einer Warteschlange Saake/Schallehn Algorithmen & Datenstrukturen II 10 10 Implementierung der Breitensuche /2 public class WeightedGraph { public final static int WHITE = 0; public final static int GRAY = 1; public final static int BLACK = 2; static class BFSItem { int color, distance, prev; public void searchbreadthfirst(int start) { Saake/Schallehn Algorithmen & Datenstrukturen II 10 11 Uni Magdeburg, WS 2005/06 151
Implementierung der Breitensuche /3 Speichert für einen Knoten: Farbe (Weiß, Grau, Schwarz), Distanz zum Ursprungsknoten, Vorgängerknoten im aufspannenden Baum static class BFSItem { int color, distance, prev; public BFSItem(int c, int d, int p) { color = c; distance = d; prev = p; Saake/Schallehn Algorithmen & Datenstrukturen II 10 12 Algorithmus Breitensuche /1 public void searchbreadthfirst(int start) { int i; BFSItem[] table = new BFSItem[labels.size()]; Queue<Integer> queue = new LinkedList<Integer>(); for (i = 0; i < table.length; i++) table[i] = new BFSItem(WHITE, Integer.MAX_VALUE, -1); table[start].color = GRAY; table[start].distance = 0; queue.offer(start); Saake/Schallehn Algorithmen & Datenstrukturen II 10 13 Algorithmus Breitensuche /2 while (! queue.isempty()) { int u = (queue.poll()).intvalue(); Iterator iter = getedges(u); while (iter.hasnext()) { Edge v = (Edge)iter.next(); if (table[v.dest].color == WHITE) { table[v.dest].color = GRAY; table[v.dest].distance = table[u].distance + v.cost; table[v.dest].prev = u; queue.offer(v.dest); table[u].color = BLACK; Saake/Schallehn Algorithmen & Datenstrukturen II 10 14 152 Uni Magdeburg, WS 2005/06
Implementierung der Tiefensuche DFS = DepthFirstSearch Implementierung als rekursiver Algorithmus Nicht-rekursive Einstiegsmethode zum sicherstellen, dass alle Knoten erreicht werden KlasseDFSItem für Traversierungszustände einzelner Knoten Saake/Schallehn Algorithmen & Datenstrukturen II 10 15 10 Implementierung der Tiefensuche /2 Speichert für einen Knoten: Farbe (Weiß, Grau, Schwarz), Vorgängerknoten im aufspannenden Baum, Beginn und Ende der Bearbeitung static class DFSItem { int color, prev, d, f; public DFSItem() { color = WHITE; prev = 0; d = f = 0; Saake/Schallehn Algorithmen & Datenstrukturen II 10 16 Algorithmus Tiefensuche /1 public void searchdepthfirst() { int i, t = 0; DFSItem[] table = new DFSItem[labels.size ()]; for (i = 0; i < table.length; i++) table[i] = new DFSItem(); for (i = 0; i < table.length; i++) if (table[i].color == WHITE) dfsvisit (i, t, table); Saake/Schallehn Algorithmen & Datenstrukturen II 10 17 Uni Magdeburg, WS 2005/06 153
Algorithmus Tiefensuche /2 private int dfsvisit(int u, int time, DFSItem[] table) { table[u].color = GRAY; table[u].d = ++time; Iterator iter = getedges(u); while (iter.hasnext()) { Edge v = (Edge)iter.next(); if (table[v.dest].color == WHITE) { table[v.dest].prev = u; time = dfsvisit(v.dest, time, table); table[u].color = BLACK; table[u].f = ++time; return time; Saake/Schallehn Algorithmen & Datenstrukturen II 10 18 154 Uni Magdeburg, WS 2005/06