/** * Determines whether the digraph <tt>G</tt> has a topological order and, if so, finds such a * topological order. * * @param G the digraph */ public TopologicalX(Digraph G) { // compute indegrees int[] indegree = new int[G.V()]; for (int v = 0; v < G.V(); v++) { for (int w : G.adj(v)) { indegree[w]++; } } // initialize rank = new int[G.V()]; order = new Queue<Integer>(); int count = 0; // initialize queue to contain all vertices with indegree = 0 Queue<Integer> queue = new Queue<Integer>(); for (int v = 0; v < G.V(); v++) if (indegree[v] == 0) queue.enqueue(v); for (int j = 0; !queue.isEmpty(); j++) { int v = queue.dequeue(); order.enqueue(v); rank[v] = count++; for (int w : G.adj(v)) { indegree[w]--; if (indegree[w] == 0) queue.enqueue(w); } } // there is a directed cycle in subgraph of vertices with indegree >= 1. if (count != G.V()) { order = null; } assert check(G); }
private int[] path(Iterable<Integer> v, Iterable<Integer> w) { boolean isWithin = true; for (int i : v) { if (i < 0 || i > G.V() - 1) isWithin = false; } for (int i : w) { if (i < 0 || i > G.V() - 1) isWithin = false; } if (!isWithin) throw new IndexOutOfBoundsException("Arguments not within [0, V-1]"); SAPPath vPath = new SAPPath(G, v); SAPPath wPath = new SAPPath(G, w); int[] distV = vPath.breath(); int[] distW = wPath.breath(); int sap = INFINITY; int distVW = INFINITY; int ancestor = INFINITY; for (int i = 0; i < G.V(); i++) { if (distV[i] != INFINITY && distW[i] != INFINITY) { distVW = distV[i] + distW[i]; if (distVW < sap) { sap = distVW; ancestor = i; } } } int[] p = {sap, ancestor}; return p; }
/** * Computes the vertices reachable from the source vertex <tt>s</tt> in the digraph <tt>G</tt>. * * @param G the digraph * @param s the source vertex */ public NonrecursiveDirectedDFS(Digraph G, int s) { marked = new boolean[G.V()]; // to be able to iterate over each adjacency list, keeping track of which // vertex in each adjacency list needs to be explored next Iterator<Integer>[] adj = (Iterator<Integer>[]) new Iterator[G.V()]; for (int v = 0; v < G.V(); v++) adj[v] = G.adj(v).iterator(); // depth-first search using an explicit stack Stack<Integer> stack = new Stack<Integer>(); marked[s] = true; stack.push(s); while (!stack.isEmpty()) { int v = stack.peek(); if (adj[v].hasNext()) { int w = adj[v].next(); // StdOut.printf("check %d\n", w); if (!marked[w]) { // discovered vertex w for the first time marked[w] = true; // edgeTo[w] = v; stack.push(w); // StdOut.printf("dfs(%d)\n", w); } } else { // StdOut.printf("%d done\n", v); stack.pop(); } } }
/** * Ejecuta una caminata aleatoria sobre un grafo dirigido. Imprime por pantalla la cantidad de * pasos que dio antes de visitar todos los nodos del grafo. * * @param G Grafo dirigido sobre el cual se desea realizar la caminata aleatoria. */ public void randomWalk(Digraph G) { int cont = 0; if (G.V() == 0) return; boolean[] viewed = new boolean[G.V()]; int node = 0; viewed[node] = true; while (!this.allTrue(viewed)) { if (G.outdegree(node) == 0) { System.out.println("Encontrado un nodo sin salida"); System.out.println("Cantidad de pasos dados en el Random Walk : " + cont); return; } int visited = this.getRandomNode(G.adj(node), G.outdegree(node)); System.out.println(node + " -> " + visited); viewed[visited] = true; cont++; node = visited; } System.out.println("Cantidad de pasos dados en el Random Walk : " + cont); }
public BreadthFirstDirectedPaths(Digraph G, int s) { marked = new boolean[G.V()]; distTo = new int[G.V()]; edgeTo = new int[G.V()]; for (int v = 0; v < G.V(); v++) distTo[v] = INFINITY; this.s = s; bfs(G, s); }
/** * Determines a depth-first order for the digraph <tt>G</tt>. * * @param G the digraph */ public DepthFirstOrder(Digraph G) { pre = new int[G.V()]; post = new int[G.V()]; postorder = new Queue<Integer>(); preorder = new Queue<Integer>(); marked = new boolean[G.V()]; for (int v = 0; v < G.V(); v++) if (!marked[v]) dfs(G, v); }
// does the id[] array contain the strongly connected components? private boolean check(Digraph G) { TransitiveClosure tc = new TransitiveClosure(G); for (int v = 0; v < G.V(); v++) { for (int w = 0; w < G.V(); w++) { if (stronglyConnected(v, w) != (tc.reachable(v, w) && tc.reachable(w, v))) return false; } } return true; }
public KosarajuSCC(Digraph G) { marked = new boolean[G.V()]; id = new int[G.V()]; DepthFirstOrder order = new DepthFirstOrder(G.reverse()); for (int s : order.reverse()) if (!marked[s]) { dfs(G, s); count++; } }
DepthFirstOrder(Digraph G) { marked = new boolean[G.V()]; pre = new LinkedList<Integer>(); post = new LinkedList<Integer>(); reversePost = new Stack<Integer>(); for (int v = 0; v < G.V(); v++) { if (!marked[v]) { dfs(G, v); } } }
/** Copy constructor. */ public Digraph(Digraph G) { this(G.V()); this.E = G.E(); for (int v = 0; v < G.V(); v++) { // reverse so that adjacency list is in same order as original Stack<Integer> reverse = new Stack<Integer>(); for (int w : G.adj[v]) { reverse.push(w); } for (int w : reverse) { adj[v].add(w); } } }
/** * Computes the strong components of the digraph <tt>G</tt>. * * @param G the digraph */ public GabowSCC(Digraph G) { marked = new boolean[G.V()]; stack1 = new Stack<Integer>(); stack2 = new Stack<Integer>(); id = new int[G.V()]; preorder = new int[G.V()]; for (int v = 0; v < G.V(); v++) id[v] = -1; for (int v = 0; v < G.V(); v++) { if (!marked[v]) dfs(G, v); } // check that id[] gives strong components assert check(G); }
/** Unit tests the <tt>DepthFirstOrder</tt> data type. */ public static void main(String[] args) { In in = new In(args[0]); Digraph G = new Digraph(in); DepthFirstOrder dfs = new DepthFirstOrder(G); StdOut.println(" v pre post"); StdOut.println("--------------"); for (int v = 0; v < G.V(); v++) { StdOut.printf("%4d %4d %4d\n", v, dfs.pre(v), dfs.post(v)); } StdOut.print("Preorder: "); for (int v : dfs.pre()) { StdOut.print(v + " "); } StdOut.println(); StdOut.print("Postorder: "); for (int v : dfs.post()) { StdOut.print(v + " "); } StdOut.println(); StdOut.print("Reverse postorder: "); for (int v : dfs.reversePost()) { StdOut.print(v + " "); } StdOut.println(); }
/** Unit tests the <tt>GabowSCC</tt> data type. */ public static void main(String[] args) { In in = new In(args[0]); Digraph G = new Digraph(in); GabowSCC scc = new GabowSCC(G); // number of connected components int M = scc.count(); StdOut.println(M + " components"); // compute list of vertices in each strong component Queue<Integer>[] components = (Queue<Integer>[]) new Queue[M]; for (int i = 0; i < M; i++) { components[i] = new Queue<Integer>(); } for (int v = 0; v < G.V(); v++) { components[scc.id(v)].enqueue(v); } // print results for (int i = 0; i < M; i++) { for (int v : components[i]) { StdOut.print(v + " "); } StdOut.println(); } }
/** Test client. */ public static void main(String[] args) { In in = new In(args[0]); Digraph G = new Digraph(in); StdOut.println(G); StdOut.println(); for (int v = 0; v < G.V(); v++) for (int w : G.adj(v)) StdOut.println(v + "->" + w); }
/** Unit tests the <tt>NonrecursiveDirectedDFS</tt> data type. */ public static void main(String[] args) { In in = new In(args[0]); Digraph G = new Digraph(in); int s = Integer.parseInt(args[1]); NonrecursiveDirectedDFS dfs = new NonrecursiveDirectedDFS(G, s); for (int v = 0; v < G.V(); v++) if (dfs.marked(v)) StdOut.print(v + " "); StdOut.println(); }
public KosarajuSCC(Digraph G) { // compute reverse postorder of reverse graph DepthFirstOrder dfs = new DepthFirstOrder(G.reverse()); // run DFS on G, using reverse postorder to guide calculation marked = new boolean[G.V()]; id = new int[G.V()]; for (int v : dfs.reversePost()) { if (!marked[v]) { dfs(G, v); count++; } } // check that id[] gives strong components assert check(G); }
public boolean recognizes(String txt) { Bag<Integer> pc = new Bag<Integer>(); DirectedDFS dfs = new DirectedDFS(G, 0); for (int v = 0; v < G.V(); v++) if (dfs.marked(v)) pc.add(v); for (int i = 0; i < txt.length(); i++) { Bag<Integer> match = new Bag<Integer>(); for (int v : pc) if (v < M) if (re[v] == txt.charAt(i) || re[v] == '.') match.add(v + 1); dfs = new DirectedDFS(G, match); pc = new Bag<Integer>(); for (int v = 0; v < G.V(); v++) if (dfs.marked(v)) pc.add(v); // optimization if no states reachable if (pc.size() == 0) return false; } for (int v : pc) if (v == M) return true; return false; }
// Determines whether a digraph has an Eulerian cycle using necessary // and sufficient conditions (without computing the cycle itself): // - at least one edge // - indegree(v) = outdegree(v) for every vertex // - the graph is connected, when viewed as an undirected graph // (ignoring isolated vertices) private static boolean hasEulerianCycle(Digraph G) { // Condition 0: at least 1 edge if (G.E() == 0) return false; // Condition 1: indegree(v) == outdegree(v) for every vertex for (int v = 0; v < G.V(); v++) if (G.outdegree(v) != G.indegree(v)) return false; // Condition 2: graph is connected, ignoring isolated vertices Graph H = new Graph(G.V()); for (int v = 0; v < G.V(); v++) for (int w : G.adj(v)) H.addEdge(v, w); // check that all non-isolated vertices are conneted int s = nonIsolatedVertex(G); BreadthFirstPaths bfs = new BreadthFirstPaths(H, s); for (int v = 0; v < G.V(); v++) if (H.degree(v) > 0 && !bfs.hasPathTo(v)) return false; return true; }
public static void main(String[] args) { In in1 = new In(Inputs.DIGRAPH_SMALL); In in2 = new In(Inputs.DIGRAPH_SMALL); edu.princeton.cs.algs4.Digraph sedgewicks = new edu.princeton.cs.algs4.Digraph(in1); Digraph digraph = new Digraph(in2); in1.close(); in2.close(); StdOut.printf("Sedgewicks - v: %d, e: %d\n", sedgewicks.V(), sedgewicks.E()); for (int i = 0; i < sedgewicks.V(); i++) { for (int w : sedgewicks.adj(i)) { StdOut.printf("%d -> %d\n", i, w); } } StdOut.println(); StdOut.printf("My - v: %d, e: %d\n", digraph.V(), digraph.E()); for (int i = 0; i < digraph.V(); i++) { for (int w : digraph.adj(i)) { StdOut.printf("%d -> %d\n", i, w); } } StdOut.println(); edu.princeton.cs.algs4.Digraph sedwickDi = sedgewicks.reverse(); StdOut.printf("Sedgewicks reverse - v: %d, e: %d\n", sedwickDi.V(), sedwickDi.E()); for (int i = 0; i < sedwickDi.V(); i++) { for (int w : sedwickDi.adj(i)) { StdOut.printf("%d -> %d\n", i, w); } } StdOut.println(); Digraph myReverse = digraph.reverse(); StdOut.printf("My reverse - v: %d, e: %d\n", myReverse.V(), myReverse.E()); for (int i = 0; i < myReverse.V(); i++) { for (int w : myReverse.adj(i)) { StdOut.printf("%d -> %d\n", i, w); } } }
private boolean rootedDAG(Digraph g) { int roots = 0; for (int i = 0; i < g.V(); i++) { if (!g.adj(i).iterator().hasNext()) { roots++; if (roots > 1) { return false; } } } return roots == 1; }
// certify that digraph is acyclic private boolean check(Digraph G) { // digraph is acyclic if (hasOrder()) { // check that ranks are a permutation of 0 to V-1 boolean[] found = new boolean[G.V()]; for (int i = 0; i < G.V(); i++) { found[rank(i)] = true; } for (int i = 0; i < G.V(); i++) { if (!found[i]) { System.err.println("No vertex with rank " + i); return false; } } // check that ranks provide a valid topological order for (int v = 0; v < G.V(); v++) { for (int w : G.adj(v)) { if (rank(v) > rank(w)) { System.err.printf( "%d-%d: rank(%d) = %d, rank(%d) = %d\n", v, w, v, rank(v), w, rank(w)); return false; } } } // check that order() is consistent with rank() int r = 0; for (int v : order()) { if (rank(v) != r) { System.err.println("order() and rank() inconsistent"); return false; } r++; } } return true; }
private int[] path(int v, int w) { if (v < 0 || w < 0 || v > G.V() - 1 || w > G.V() - 1) throw new IndexOutOfBoundsException("Arguments not within [0, V-1]"); SAPPath vPath = new SAPPath(G, v); SAPPath wPath = new SAPPath(G, w); int[] distV = vPath.breath(); int[] distW = wPath.breath(); int sap = INFINITY; int distVW = INFINITY; int ancestor = INFINITY; for (int i = 0; i < G.V(); i++) { if (distV[i] != INFINITY && distW[i] != INFINITY) { distVW = distV[i] + distW[i]; if (distVW < sap) { sap = distVW; ancestor = i; } } } int[] p = {sap, ancestor}; return p; }
/** Unit tests the <tt>DirectedEulerianCycle</tt> data type. */ public static void main(String[] args) { int V = Integer.parseInt(args[0]); int E = Integer.parseInt(args[1]); // Eulerian cycle Digraph G1 = DigraphGenerator.eulerianCycle(V, E); unitTest(G1, "Eulerian cycle"); // Eulerian path Digraph G2 = DigraphGenerator.eulerianPath(V, E); unitTest(G2, "Eulerian path"); // empty digraph Digraph G3 = new Digraph(V); unitTest(G3, "empty digraph"); // self loop Digraph G4 = new Digraph(V); int v4 = StdRandom.uniform(V); G4.addEdge(v4, v4); unitTest(G4, "single self loop"); // union of two disjoint cycles Digraph H1 = DigraphGenerator.eulerianCycle(V / 2, E / 2); Digraph H2 = DigraphGenerator.eulerianCycle(V - V / 2, E - E / 2); int[] perm = new int[V]; for (int i = 0; i < V; i++) perm[i] = i; StdRandom.shuffle(perm); Digraph G5 = new Digraph(V); for (int v = 0; v < H1.V(); v++) for (int w : H1.adj(v)) G5.addEdge(perm[v], perm[w]); for (int v = 0; v < H2.V(); v++) for (int w : H2.adj(v)) G5.addEdge(perm[V / 2 + v], perm[V / 2 + w]); unitTest(G5, "Union of two disjoint cycles"); // random digraph Digraph G6 = DigraphGenerator.simple(V, E); unitTest(G6, "simple digraph"); }
/** * Computes an Eulerian cycle in the specified digraph, if one exists. * * @param G the digraph */ public DirectedEulerianCycle(Digraph G) { // must have at least one edge if (G.E() == 0) return; // necessary condition: indegree(v) = outdegree(v) for each vertex v // (without this check, DFS might return a path instead of a cycle) for (int v = 0; v < G.V(); v++) if (G.outdegree(v) != G.indegree(v)) return; // create local view of adjacency lists, to iterate one vertex at a time Iterator<Integer>[] adj = (Iterator<Integer>[]) new Iterator[G.V()]; for (int v = 0; v < G.V(); v++) adj[v] = G.adj(v).iterator(); // initialize stack with any non-isolated vertex int s = nonIsolatedVertex(G); Stack<Integer> stack = new Stack<Integer>(); stack.push(s); // greedily add to putative cycle, depth-first search style cycle = new Stack<Integer>(); while (!stack.isEmpty()) { int v = stack.pop(); while (adj[v].hasNext()) { stack.push(v); v = adj[v].next(); } // add vertex with no more leaving edges to cycle cycle.push(v); } // check if all edges have been used // (in case there are two or more vertex-disjoint Eulerian cycles) if (cycle.size() != G.E() + 1) cycle = null; assert certifySolution(G); }
/** Unit tests the <tt>DirectedDFS</tt> data type. */ public static void main(String[] args) { // read in digraph from command-line argument In in = new In(args[0]); Digraph G = new Digraph(in); // read in sources from command-line arguments Bag<Integer> sources = new Bag<Integer>(); for (int i = 1; i < args.length; i++) { int s = Integer.parseInt(args[i]); sources.add(s); } // multiple-source reachability DirectedDFS dfs = new DirectedDFS(G, sources); // print out vertices reachable from sources for (int v = 0; v < G.V(); v++) { if (dfs.marked(v)) StdOut.print(v + " "); } StdOut.println(); }
public EdgeWeightedCycleFinder(Digraph G){ onStack = new boolean[G.V()]; edgeTo =new int[G.V()]; marked =new boolean[G.V()]; for(int v=0;v<G.V();v++) if(!marked[v]) dfs(G,v); }
public NFADemo(String regexp) { // use stack to keep track of the positions of '('and '|' // issue : or的优先级最低 Stack<Integer> ops = new Stack<Integer>(); re = regexp.toCharArray(); M = re.length; G = new Digraph(M + 1); // 第一次遍历,确定层次,仅为作图用 int[] levels = new int[M]; // levels仅在 * 和 | 处非零 for (int i = 0; i < M; i++) { int lp = i; if (re[i] == '(' || re[i] == '|') ops.push(i); else if (re[i] == ')') { int or = ops.pop(); if (re[or] == '|') { lp = ops.pop(); levels[or] = maxOfArr(levels, lp, i) + 1; } else lp = or; } if (i < M - 1 && re[i + 1] == '*') levels[i + 1] = maxOfArr(levels, lp, i + 1) + 1; } int maxLevel = maxOfArr(levels, 0, M); StdDraw.setCanvasSize(800, 800 * 2 * maxLevel / M); StdDraw.setXscale(0, M); StdDraw.setYscale(-maxLevel, maxLevel); double r = 0.2; for (int v = 0; v < G.V(); v++) { if (v < M) { StdDraw.circle((double) v, 0.0, r); StdDraw.text((double) v, 0.0, (new Character(re[v]).toString())); } else StdDraw.filledCircle((double) v, 0.0, r); } StdDraw.setPenColor(StdDraw.RED); StdDraw.setPenRadius(0.005); ops = new Stack<Integer>(); for (int i = 0; i < M; i++) { int lp = i; if (re[i] == '(' || re[i] == '|') ops.push(i); else if (re[i] == ')') { int or = ops.pop(); if (re[or] == '|') { lp = ops.pop(); G.addEdge(lp, or + 1); G.addEdge(or, i); // connect (lp, or+1), (or, i) double level = (double) levels[or]; StdDraw.line(or, r, or, level); StdDraw.line(or, level, i, level); StdDraw.arrow(i, level, i, r); StdDraw.line(lp, -r, lp, -level); StdDraw.line(lp, -level, or + 1, -level); StdDraw.filledArrow(or + 1, -level, or + 1, -r); } else lp = or; // 此时是'(', 在后面跟的是*时会用到 } if (i < M - 1 && re[i + 1] == '*') { // look ahead G.addEdge(lp, i + 1); G.addEdge(i + 1, lp); // connect (lp, i+1), (i+1, lp) double level = (double) levels[i + 1]; StdDraw.line(i + 1, r, i + 1, level); StdDraw.line(i + 1, level, lp, level); StdDraw.filledArrow(lp, level, lp, r); StdDraw.line(lp, -r, lp, -level); StdDraw.line(lp, -level, i + 1, -level); StdDraw.filledArrow(i + 1, -level, i + 1, -r); } if (re[i] == '(' || re[i] == '*' || re[i] == ')') { G.addEdge(i, i + 1); StdDraw.filledArrow(i + r, 0.0, i + 1 - r, 0.0); } else if (re[i] != '|') { // match transitions StdDraw.setPenColor(); StdDraw.filledArrow(i + r, 0.0, i + 1 - r, 0.0); StdDraw.setPenColor(StdDraw.RED); } } }
/** * Determines whether the digraph <tt>G</tt> has a directed cycle and, if so, finds such a cycle. * * @param G the digraph */ public DirectedCycle(Digraph G) { marked = new boolean[G.V()]; onStack = new boolean[G.V()]; edgeTo = new int[G.V()]; for (int v = 0; v < G.V(); v++) if (!marked[v]) dfs(G, v); }
/** * Computes the vertices in digraph <tt>G</tt> that are connected to any of the source vertices * <tt>sources</tt>. * * @param G the graph * @param sources the source vertices */ public DirectedDFS(Digraph G, Iterable<Integer> sources) { marked = new boolean[G.V()]; for (int v : sources) { if (!marked[v]) dfs(G, v); } }
/** * Computes the vertices in digraph <tt>G</tt> that are reachable from the source vertex * <tt>s</tt>. * * @param G the digraph * @param s the source vertex */ public DirectedDFS(Digraph G, int s) { marked = new boolean[G.V()]; dfs(G, s); }