10 Graphenalgorithmen in Java 10.1 Implementierung eines gewichteten Graphen 10.2 Implementierung der Breitensuche 10 10.3 Implementierung der Tiefensuche 147 10 Graphenalgorithmen in Java 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 148 Algorithmen & Datenstrukturen II 10–2 Uni Magdeburg, WS 2005/06 10 Graphenalgorithmen in Java 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 } 10–3 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 Uni Magdeburg, WS 2005/06 10–5 149 10 Graphenalgorithmen in Java 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 150 Algorithmen & Datenstrukturen II 10–8 Uni Magdeburg, WS 2005/06 10 Graphenalgorithmen in Java Testrahmen: gerichteter Graph Saake/Schallehn "x", 1); "y", 1); "y", 1); ß", 1); Algorithmen & Datenstrukturen II 10 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”, g2.addEdge(”x”, ”v”, 1); g2.addEdge("v", g2.addEdge(”y”, ”x”, 1); g2.addEdge("w", g2.addEdge(”z”, ”z”, 1); g2.addEdge("w", g2.searchDepthFirst(); 10–9 Implementierung der Breitensuche ◮ ◮ BFS = BreadthFirstSearch Implementierung als iterativer Algorithmus ◮ ◮ ◮ Konstanten für Farbmarkierungen Klasse BFSItem 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 Uni Magdeburg, WS 2005/06 10–11 151 10 Graphenalgorithmen in Java 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 152 Algorithmen & Datenstrukturen II 10–14 Uni Magdeburg, WS 2005/06 10 Graphenalgorithmen in Java Implementierung der Tiefensuche ◮ DFS = DepthFirstSearch ◮ Implementierung als rekursiver Algorithmus ◮ Nicht-rekursive Einstiegsmethode zum sicherstellen, dass alle Knoten erreicht werden Klasse DFSItem für Traversierungszustände einzelner Knoten Saake/Schallehn Algorithmen & Datenstrukturen II 10 ◮ 10–15 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 Uni Magdeburg, WS 2005/06 10–17 153 10 Graphenalgorithmen in Java 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 154 Algorithmen & Datenstrukturen II 10–18 Uni Magdeburg, WS 2005/06