/** * Diese Zeile ist fuer jede *.java-Datei noetig, damit der Compiler weiss, wo er zu suchen hat. */ package junit_libs; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Queue; /** * * @coauthor christian * @modified 23.04.2009, chbauman: * Interne Klassen auf 'protected' gesetzt. * Interne Zustaende der internen Klassen 'public' gesetzt. * Kommentare und Formatierung. */ public class GraphOriginal { public final static int WHITE = 0; public final static int GRAY = 1; public final static int BLACK = 2; /** * Nutze statt des Modifiers 'default' 'protected', so dass Kindklassen von * GraphOriginal auf Edge zugreifen koennen. */ protected class Edge { // Da in der Kindklasse auf diese Werte zugegriffen werden koennte, setze sie 'public'. public int dest, cost; public Edge(int d, int c) { dest = d; cost = c; } public String toString() { return new String(dest + "(" + cost + ")"); } } /** * @see Edge Kommentar */ protected class BFSItem { // Da in der Kindklasse auf diese Werte zugegriffen werden koennte, setze sie 'public'. public int color, distance, prev; public BFSItem(int c, int d, int p) { color = c; distance = d; prev = p; } } /** * @see Edge Kommentar */ protected class DFSItem { // Da in der Kindklasse auf diese Werte zugegriffen werden koennte, setze sie 'public'. public int color, prev, d, f; public DFSItem() { color = WHITE; prev = 0; d = f = 0; } } protected List labels; /* * Lege nodes als eine List von List mit Edges als Füllung an. */ protected List> nodes; public GraphOriginal() { // Okay, labels ist eine List - ArrayList ist die Implementierungsklasse in unserem Fall. labels = new ArrayList(); /* * nodes ist eine List>. * Wir definieren nun, dass eine ArrayList unbestimmte List-Instanzen mit Edge-Objekten haelt. * Dadurch koennen wir in unsere ArrayList jede erdenkliche andere List reinstecken. * * Wuerden wir ArrayList> sagen, waere das zu restriktiv, da nodes oben als * "generelle List-Instanz von einer generellen List-Instanz von Edge-Objekten" ist. * nodes sieht ja nach aussen nur als List> aus, weswegen wir * * nodes.add(new LinkedList()); * nodes.add(new ArrayList()); * * aufrufen koennten. Die erste zuweisung wird dann aber fehlschlagen, da man eine LinkedList * nicht als ArrayList ausgeben kann. */ nodes = new ArrayList>(); } public static void main(String[] args) { } public void addNode(String label) { if (labels.contains(label)) throw new RuntimeException("Node already defined"); nodes.add(new ArrayList()); int idx = nodes.size() - 1; labels.add(idx, label); } public int getNodeID(String label) { int i = labels.indexOf(label); if (i == -1) throw new RuntimeException("no such element"); return i; } public void addEdge(String src, String dest, int cost) { nodes.get(getNodeID(src)).add((new Edge(getNodeID(dest), cost))); } public void searchBreadthFirst(int start) { int i; BFSItem[] table = new BFSItem[labels.size()]; Queue queue = new LinkedList(); 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); while (!queue.isEmpty()) { int u = queue.poll(); for (Edge e : nodes.get(u)) { if (table[e.dest].color == WHITE) { table[e.dest].color = GRAY; table[e.dest].distance = table[u].distance + 1; table[e.dest].prev = u; queue.offer(e.dest); } } table[u].color = BLACK; System.out.println("vertex #" + u + ": " + table[u].distance); } } int time; public void searchDepthFirst() { time = 0; int i = 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, table); } private void dfsVisit(int nr, DFSItem[] table) { table[nr].color = GRAY; table[nr].d = ++time; for (Edge e : nodes.get(nr)) { if (table[e.dest].color == WHITE) { table[e.dest].prev = nr; dfsVisit(e.dest, table); } } table[nr].color = BLACK; table[nr].f = ++time; System.out.println("vertex #" + nr + ": " + table[nr].d + ", " + table[nr].f); } public String toString() { String s = ""; for (String l : labels) { s += l + "(" + getNodeID(l) + ")" + " -> " + nodes.get(getNodeID(l)) + "\n"; } return s; } }