From d4a674a72ba90f4badbeb1460371065a70980541 Mon Sep 17 00:00:00 2001 From: Rohit Kumar Date: Wed, 9 Aug 2017 23:26:47 +0100 Subject: [PATCH] Adding Graph Algorithms --- ConnectedComponents.java | 102 ++++++++ Cycle.java | 87 +++++++ DFSPaths.java | 96 ++++++++ DegreeOfSeparation.java | 111 +++++++++ DiGraph.java | 288 ++++++++++++++++++++++ Dijkstras.java | 138 +++++++++++ DirectedCycle.java | 92 +++++++ Graph.java | 502 +++++++++++++++++++-------------------- SymbolGraph.java | 66 +++++ TopologicalSort.java | 98 ++++++++ TwoColor.java | 100 ++++++++ 11 files changed, 1429 insertions(+), 251 deletions(-) create mode 100644 ConnectedComponents.java create mode 100644 Cycle.java create mode 100644 DFSPaths.java create mode 100644 DegreeOfSeparation.java create mode 100644 DiGraph.java create mode 100644 Dijkstras.java create mode 100644 DirectedCycle.java create mode 100644 SymbolGraph.java create mode 100644 TopologicalSort.java create mode 100644 TwoColor.java diff --git a/ConnectedComponents.java b/ConnectedComponents.java new file mode 100644 index 0000000..a6f623c --- /dev/null +++ b/ConnectedComponents.java @@ -0,0 +1,102 @@ +package com.program.graph.algo; + +import java.util.ArrayList; +import java.util.List; + +public class ConnectedComponents { + + private int [] connectedId; + private int processCount; + + public ConnectedComponents(Graph g) { + this.connectedId = new int[g.getVertices().size()]; + this.processCount = 0; + populateConnectedId(g); + } + + public void populateConnectedId(Graph g){ + + for (Graph.Vertex v : g.getVertices()) { + if (!v.visited){ + dfs(g, v); + processCount++; + } + } + } + + public void dfs(Graph g, Graph.Vertex v){ + + v.visited = true; + connectedId[g.getIndexOf(v)] = processCount; + for (Graph.Edge e : v.getEdges()) { + if (!e.getTo().visited) { + dfs(g,e.getTo()); + } + } + } + + + public boolean isConnected(Graph g, Graph.Vertex v, Graph.Vertex w){ + return connectedId[g.getIndexOf(v)] == connectedId[g.getIndexOf(w)]; + } + + public static void main(String[] args) { + List vertices = new ArrayList(); + Graph.Vertex A = new Graph.Vertex('A'); + /* + * If Inner class graph and edge were not static then + * First we have to instantiate Graph and then vertex/edge + * eg : + * Grapg g1 = new Graph(); + * Graph.vertex A = g1.new Vertex('A'); + * + */ + Graph.Vertex B = new Graph.Vertex('B'); + Graph.Vertex C = new Graph.Vertex('C'); + Graph.Vertex D = new Graph.Vertex('D'); + Graph.Vertex E = new Graph.Vertex('E'); + Graph.Vertex F = new Graph.Vertex('F'); + Graph.Vertex G = new Graph.Vertex('G'); + Graph.Vertex H = new Graph.Vertex('H'); + Graph.Vertex I = new Graph.Vertex('I'); + Graph.Vertex J = new Graph.Vertex('J'); + Graph.Vertex K = new Graph.Vertex('K'); + Graph.Vertex L = new Graph.Vertex('L'); + vertices.add(A); + vertices.add(B); + vertices.add(C); + vertices.add(D); + vertices.add(E); + vertices.add(F); + vertices.add(G); + vertices.add(H); + vertices.add(I); + vertices.add(J); + vertices.add(K); + vertices.add(L); + + List edges = new ArrayList(); + edges.add(new Graph.Edge(0,A,B)); + edges.add(new Graph.Edge(0,B,C)); + edges.add(new Graph.Edge(0,B,H)); + edges.add(new Graph.Edge(0,C,D)); + edges.add(new Graph.Edge(0,C,E)); + edges.add(new Graph.Edge(0,E,H)); + edges.add(new Graph.Edge(0,E,F)); + edges.add(new Graph.Edge(0,E,G)); + + edges.add(new Graph.Edge(0,I,J)); + edges.add(new Graph.Edge(0,J,K)); + edges.add(new Graph.Edge(0,I,L)); + edges.add(new Graph.Edge(0,I,K)); + + + Graph g = new Graph(vertices, edges); + ConnectedComponents cc = new ConnectedComponents(g); + System.out.println("A is Connected to G ::: "+cc.isConnected(g, A, G)); + System.out.println("I is Connected to A ::: "+cc.isConnected(g, I, A)); + System.out.println("I is Connected to K ::: "+cc.isConnected(g, I, K)); + + } + +} diff --git a/Cycle.java b/Cycle.java new file mode 100644 index 0000000..209ba7a --- /dev/null +++ b/Cycle.java @@ -0,0 +1,87 @@ +package com.program.graph.algo; + +import java.util.ArrayList; +import java.util.List; + +public class Cycle { + + private boolean hasCycle; + + public Cycle(Graph g){ + + for (Graph.Vertex v: g.getVertices()) { + if (!v.visited) { + dfs(g, v, v); + } + } + } + + /* + * For each vertex we have three option + * 1> Either next vertex will be unvisited, then simply call dfs(q, w, prev) + * 2> Or next vertex is visited. then we go to else part + * 3> if (w != prev), here if w == prev means w next vertex is same vertex we are coming from + * and if its visited and its not equal to prev then we have encountered loop in graph. + * coz this vertex w is already visited and its not equal to prev vertex. + */ + public void dfs(Graph g, Graph.Vertex v, Graph.Vertex prevVertex ){ + + v.visited = true; + Graph.Vertex w; + for (Graph.Edge e : v.getEdges()) { + w = e.getTo(); + if (!w.visited) { + dfs(g, w, v); // here v is previous visited vertex + }else if (w != prevVertex){ + hasCycle = true; + } + } + } + + public boolean hasCycle(){ + return hasCycle; + } + + public static void main(String[] args) { + List vertices = new ArrayList(); + Graph.Vertex A = new Graph.Vertex('A'); + /* + * If Inner class graph and edge were not static then + * First we have to instantiate Graph and then vertex/edge + * eg : + * Grapg g1 = new Graph(); + * Graph.vertex A = g1.new Vertex('A'); + * + */ + Graph.Vertex B = new Graph.Vertex('B'); + Graph.Vertex C = new Graph.Vertex('C'); + Graph.Vertex D = new Graph.Vertex('D'); + Graph.Vertex E = new Graph.Vertex('E'); + Graph.Vertex F = new Graph.Vertex('F'); + Graph.Vertex G = new Graph.Vertex('G'); + Graph.Vertex H = new Graph.Vertex('H'); + vertices.add(A); + vertices.add(B); + vertices.add(C); + vertices.add(D); + vertices.add(E); + vertices.add(F); + vertices.add(G); + vertices.add(H); + + List edges = new ArrayList(); + edges.add(new Graph.Edge(0,A,B)); + edges.add(new Graph.Edge(0,B,C)); + edges.add(new Graph.Edge(0,B,H)); + edges.add(new Graph.Edge(0,C,D)); + edges.add(new Graph.Edge(0,C,E)); + edges.add(new Graph.Edge(0,E,H)); + edges.add(new Graph.Edge(0,E,F)); + edges.add(new Graph.Edge(0,E,G)); + + Graph g = new Graph(vertices, edges); + Cycle cyc = new Cycle(g); + System.out.println("Graph has cycle ::: "+cyc.hasCycle()); + } + +} diff --git a/DFSPaths.java b/DFSPaths.java new file mode 100644 index 0000000..be7d743 --- /dev/null +++ b/DFSPaths.java @@ -0,0 +1,96 @@ +package com.program.graph.algo; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +public class DFSPaths { + private Graph.Vertex [] edgeTo; + private boolean visited[]; + + /* + * its a recursive approach no need of method getAdjUnvisitedVertex() + */ + public void dfs(Graph g, Graph.Vertex v){ + + //visited[g.getIndexOf(v)] = true; + v.visited = true; + for (Graph.Edge e : v.getEdges()) { + Graph.Vertex w = e.getTo(); + if (!w.visited) { + edgeTo[g.getIndexOf(w)] = v; // edge path, it says how can w access from v, like edgTo[B] = A;, if we are starting from A, + dfs(g, w); + } + } + + } + + + /* + * Used stack coz want to print path in source to target order else + * we can print it in target to source order without using stack + */ + public void printPath(Graph g, Graph.Vertex source, Graph.Vertex target){ + Stack path = new Stack(); + + for(Graph.Vertex v = target; v != source; v = edgeTo[g.getIndexOf(v)]){ + path.add(v); + } + path.add(source); + //print paths + while (!path.isEmpty()) { + System.out.println(path.pop()); + } + } + + + public DFSPaths(int size) { + edgeTo = new Graph.Vertex[size]; + visited = new boolean[size]; + } + + public static void main(String[] args) { + List vertices = new ArrayList(); + Graph.Vertex A = new Graph.Vertex('A'); + /* + * If Inner class graph and edge were not static then + * First we have to instantiate Graph and then vertex/edge + * eg : + * Grapg g1 = new Graph(); + * Graph.vertex A = g1.new Vertex('A'); + * + */ + Graph.Vertex B = new Graph.Vertex('B'); + Graph.Vertex C = new Graph.Vertex('C'); + Graph.Vertex D = new Graph.Vertex('D'); + Graph.Vertex E = new Graph.Vertex('E'); + Graph.Vertex F = new Graph.Vertex('F'); + Graph.Vertex G = new Graph.Vertex('G'); + Graph.Vertex H = new Graph.Vertex('H'); + vertices.add(A); + vertices.add(B); + vertices.add(C); + vertices.add(D); + vertices.add(E); + vertices.add(F); + vertices.add(G); + vertices.add(H); + + List edges = new ArrayList(); + edges.add(new Graph.Edge(0,A,B)); + edges.add(new Graph.Edge(0,B,C)); + edges.add(new Graph.Edge(0,B,H)); + edges.add(new Graph.Edge(0,C,D)); + edges.add(new Graph.Edge(0,C,E)); + edges.add(new Graph.Edge(0,E,H)); + edges.add(new Graph.Edge(0,E,F)); + edges.add(new Graph.Edge(0,E,G)); + + Graph g = new Graph(vertices, edges); + DFSPaths dfs = new DFSPaths(g.getVertices().size()); + dfs.dfs(g, A); + dfs.printPath(g, A, F); + + } + +} diff --git a/DegreeOfSeparation.java b/DegreeOfSeparation.java new file mode 100644 index 0000000..8d25f48 --- /dev/null +++ b/DegreeOfSeparation.java @@ -0,0 +1,111 @@ +package com.program.graph.algo; + +import java.util.*; + +/* + * Expedia---- + * I rephrase the original question as the following: Let say in Facebook, + * given two person A and B. Write a function to find out whether A is a friend or a friend + * of a friend of ... of B. + */ + +/* + * Consider any social networking website like facebook etc. + * Design an algorithm / function that calculates minimum degree of connection + * between given two users. Assume that you are have already written function that + * returns a list of friends of given user : + * getFriends(username/id) : its similar to getting no of edges for the given vertex. + */ + + +public class DegreeOfSeparation { + + DiGraph.Vertex [] pathTo; + + public DegreeOfSeparation(int size){ + pathTo = new DiGraph.Vertex[size]; + } + + /* + * Traverse till target vertex t is not visited,once t is visited hence we have found + * the shortest path between given friend A and B. + */ + public void bfs(DiGraph g, DiGraph.Vertex v, DiGraph.Vertex t){ + Queue queue = new ArrayDeque<>(g.getVertices().size()); + queue.add(v); + v.setVisited(true); + DiGraph.Vertex w; + boolean found = false; + while (!queue.isEmpty() && !found) { + v = queue.remove(); + for (DiGraph.Edge e : v.getEdges()) { + w = e.getTo(); + if (!w.isVisited()) { + queue.add(w); + w.setVisited(true); + pathTo[g.getIndexOf(w)] = v; + } + if (t.isVisited()) { + found = true; // traverse till t is not visited + break; + } + } + } + } + + public void printPath(DiGraph g, DiGraph.Vertex s, DiGraph.Vertex t){ + //call bfs to prepare the path + bfs(g, s, t); + Stack stack = new Stack(); + for (DiGraph.Vertex x = t; x != s; x = pathTo[g.getIndexOf(x)]) { + stack.add(x); + } + stack.add(s); + + System.out.println("Shortest Path Between Source and Target"); + while (!stack.isEmpty()) { + System.out.println(stack.pop()); + } + + //or if we want to print in format A is friend of a Friend of B + System.out.println("["+s+"] is friend"); + for (DiGraph.Vertex x = t; x != s; x = pathTo[g.getIndexOf(x)]) { + System.out.println("of a friend"); + } + System.out.println(" of ["+t+"] "); + } + + public static void main(String[] args) { + List vertices = new ArrayList(); + DiGraph.Vertex A = new DiGraph.Vertex("A"); + DiGraph.Vertex B = new DiGraph.Vertex("B"); + DiGraph.Vertex C = new DiGraph.Vertex("C"); + DiGraph.Vertex D = new DiGraph.Vertex("D"); + DiGraph.Vertex E = new DiGraph.Vertex("E"); + DiGraph.Vertex F = new DiGraph.Vertex("F"); + DiGraph.Vertex G = new DiGraph.Vertex("G"); + DiGraph.Vertex H = new DiGraph.Vertex("H"); + vertices.add(A); + vertices.add(B); + vertices.add(C); + vertices.add(D); + vertices.add(E); + vertices.add(F); + vertices.add(G); + vertices.add(H); + + List edges = new ArrayList(); + edges.add(new DiGraph.Edge(0,A,B)); + edges.add(new DiGraph.Edge(0,B,C)); + edges.add(new DiGraph.Edge(0,H,B)); + edges.add(new DiGraph.Edge(0,C,D)); + edges.add(new DiGraph.Edge(0,C,E)); + edges.add(new DiGraph.Edge(0,E,H)); + edges.add(new DiGraph.Edge(0,E,F)); + edges.add(new DiGraph.Edge(0,E,G)); + + DiGraph g = new DiGraph(DiGraph.TYPE.UNDIRECTED, vertices, edges); + DegreeOfSeparation dgs = new DegreeOfSeparation(g.getVertices().size()); + dgs.printPath(g, A, G); + } +} diff --git a/DiGraph.java b/DiGraph.java new file mode 100644 index 0000000..ae64502 --- /dev/null +++ b/DiGraph.java @@ -0,0 +1,288 @@ +package com.program.graph.algo; + +import java.util.ArrayList; +import java.util.List; + +public class DiGraph { + + private List vertices = new ArrayList(); + private List edges = new ArrayList(); + public int vertexCount; + + private Vertex [] edgeTo; + + public enum TYPE{ + DIRECTED, UNDIRECTED; + }; + + private TYPE type; + + public DiGraph(){ + this.type=TYPE.DIRECTED; + } + + public DiGraph(TYPE type){ + this.type=type; + } + + public DiGraph(TYPE type, List vertices, List edges){ + this(type); + this.vertices.addAll(vertices); + this.edges.addAll(edges); + this.vertexCount = vertices.size(); + + for (Edge e : edges){ + Vertex from = e.from; + Vertex to = e.to; + + if (!vertices.contains(from) || !vertices.contains(to)){ + continue; + } + + int index = vertices.indexOf(from); + from = vertices.get(index); + index = vertices.indexOf(to); + to = vertices.get(index); // only if u want reciprocal edge to be added + + from.addEdge(e); + + if (this.type == TYPE.UNDIRECTED) { + Edge reciprocal = new Edge(to, from); + to.addEdge(reciprocal); + this.edges.add(reciprocal); + } + + } + } + + public DiGraph(DiGraph g){ + /* + * Copy the vertices which copies edges + */ + for (Vertex v : g.vertices) { + this.vertices.add(new Vertex(v)); + } + /* + * update the object references i.e update edges + */ + for (Vertex v : this.vertices){ + for (Edge e : v.edges) { + Vertex from = e.from; + Vertex to = e.to; + int index = this.vertices.indexOf(from); + e.from = this.vertices.get(index); + index = this.vertices.indexOf(to); + e.to = this.vertices.get(index); + this.edges.add(e); + } + } + + } + + public int getIndexOf(Vertex v){ + return this.vertices.indexOf(v); + } + + /* + * Returns the reveres DiGraph of the current graph. + */ + public DiGraph reverse(){ + DiGraph R = new DiGraph(); + + for (Vertex v : vertices){ + R.vertices.add(new Vertex(v)); + } + + for (Vertex v : R.vertices) { + for (Edge e : v.edges) { + Vertex from = e.from; + Vertex to = e.to; + int index = R.vertices.indexOf(to); + e.from = R.vertices.get(index); + index = R.vertices.indexOf(from); + e.to = R.vertices.get(index); + R.edges.add(e); + } + } + return R; + } + + public void dfs(DiGraph g, Vertex v){ + v.visited=true; + System.out.println("-"+v); + for (Edge e : v.edges) { + Vertex w = e.to; + if (!w.visited) { + edgeTo[g.getIndexOf(w)] = v; + dfs(g, w); + } + } + } + + + public List getVertices() { + return vertices; + } + + public void setVertices(List vertices) { + this.vertices = vertices; + } + + public List getEdges() { + return edges; + } + + public void setEdges(List edges) { + this.edges = edges; + } + + public Vertex[] getEdgeTo() { + return edgeTo; + } + + public void setEdgeTo(Vertex[] edgeTo) { + this.edgeTo = edgeTo; + } + + public TYPE getType() { + return type; + } + + public void setType(TYPE type) { + this.type = type; + } + + + public static class Vertex{ + private String label; + private List edges = new ArrayList(); + private int weight; + private boolean visited; + + public Vertex(){ + weight = 0; + visited = false; + } + + public Vertex(String label){ + this(); + this.label=label; + } + + public Vertex(Vertex v){ + this(v.label); + for (Edge e : v.edges) { + edges.add(new Edge(e.from, e.to)); + } + + } + + public void addEdge(Edge e){ + this.edges.add(e); + } + + public boolean equals(Object obj){ + + if ( !(obj instanceof Vertex) && obj != null) { + return false; + } + + Vertex v = (Vertex)obj; + if (!this.label.equals(v.label)){ + return false; + } + + if (this.weight != v.weight){ + return false; + } + + return true; + } + + public String getLabel() { + return label; + } + + public void setLabel(String label) { + this.label = label; + } + + public List getEdges() { + return edges; + } + + public void setEdges(List edges) { + this.edges = edges; + } + + public int getWeight() { + return weight; + } + + public void setWeight(int weight) { + this.weight = weight; + } + + public boolean isVisited() { + return visited; + } + + public void setVisited(boolean visited) { + this.visited = visited; + } + + public String toString(){ + return "Vertex["+this.label+"] -- Weight = "+this.weight; + } + + + } + + public static class Edge{ + + private Vertex from; + private Vertex to; + private int cost; + + public Edge(int cost){ + this.cost = 0; + } + + public Edge(Vertex from, Vertex to){ + this(0); + this.from=from; + this.to=to; + } + + public Edge(int cost, Vertex from, Vertex to){ + this(from, to); + this.cost=cost; + } + + public Vertex getFrom() { + return from; + } + + public void setFrom(Vertex from) { + this.from = from; + } + + public Vertex getTo() { + return to; + } + + public void setTo(Vertex to) { + this.to = to; + } + + public int getCost() { + return cost; + } + + public void setCost(int cost) { + this.cost = cost; + } + + } + +} diff --git a/Dijkstras.java b/Dijkstras.java new file mode 100644 index 0000000..87ce663 --- /dev/null +++ b/Dijkstras.java @@ -0,0 +1,138 @@ +package com.program.graph.algo; + +import java.util.ArrayList; +import java.util.List; +import java.util.Queue; +import java.util.concurrent.ArrayBlockingQueue; + +public class Dijkstras { + + private int distance[]; + private DiGraph.Vertex [] path; + private final static int INT_MAX = 999999; + + public Dijkstras(DiGraph g){ + distance = new int[g.vertexCount]; + for (int i=0; i pq = new ArrayBlockingQueue(g.vertexCount); + pq.add(s); + distance[g.getIndexOf(s)] = 0; + + while (!pq.isEmpty()) { + v = pq.remove(); + + for (DiGraph.Edge e : v.getEdges()){ + w = e.getTo(); + wIndex = g.getIndexOf(w); + d = distance[g.getIndexOf(v)] + w.getWeight() + 1; + if (distance[wIndex] == -1) { + distance[wIndex] = d; + pq.add(w); + path[wIndex] = v; + } + if (distance[wIndex] > d) { + distance[wIndex] = d; + pq.add(w); + path[wIndex] = v; + } + } + } + } + + /* + * It will consider negative edges as well + * in this we intialise distance[] with INT_MAX value, so that we can only update in case + * distance[w] > distance[v] + w.weight; + */ + public void bellmanFordAlgo(DiGraph g, DiGraph.Vertex s){ + + for (int i=0; i q = new ArrayBlockingQueue(g.vertexCount); + q.add(s); + distance[g.getIndexOf(s)] = 0; + + while (!q.isEmpty()){ + v = q.remove(); + for (DiGraph.Edge e : v.getEdges()) { + w = e.getTo(); + wIndex = g.getIndexOf(w); + d = distance[g.getIndexOf(v)] + w.getWeight() + 1; + if (distance[wIndex] > d){ + distance[wIndex]=d; + path[wIndex] = v; + if (!q.contains(w)) { + q.add(w); + } + } + } + } + + + } + public static void main(String[] args) { + List vertices = new ArrayList(); + DiGraph.Vertex A = new DiGraph.Vertex("A"); + /* + * If Inner class graph and edge were not static then + * First we have to instantiate Graph and then vertex/edge + * eg : + * Grapg g1 = new Graph(); + * Graph.vertex A = g1.new Vertex('A'); + * + */ + DiGraph.Vertex B = new DiGraph.Vertex("B"); + DiGraph.Vertex C = new DiGraph.Vertex("C"); + DiGraph.Vertex D = new DiGraph.Vertex("D"); + DiGraph.Vertex E = new DiGraph.Vertex("E"); + DiGraph.Vertex F = new DiGraph.Vertex("F"); + DiGraph.Vertex G = new DiGraph.Vertex("G"); + DiGraph.Vertex H = new DiGraph.Vertex("H"); + vertices.add(A); + vertices.add(B); + vertices.add(C); + vertices.add(D); + vertices.add(E); + vertices.add(F); + vertices.add(G); + vertices.add(H); + + List edges = new ArrayList(); + edges.add(new DiGraph.Edge(0,A,B)); + edges.add(new DiGraph.Edge(0,B,C)); + edges.add(new DiGraph.Edge(0,H,B)); + edges.add(new DiGraph.Edge(0,C,D)); + edges.add(new DiGraph.Edge(0,C,E)); + edges.add(new DiGraph.Edge(0,E,H)); + edges.add(new DiGraph.Edge(0,E,F)); + edges.add(new DiGraph.Edge(0,E,G)); + + DiGraph g = new DiGraph(DiGraph.TYPE.DIRECTED, vertices, edges); + Dijkstras dj = new Dijkstras(g); + dj.dijkstraAlgo(g, A); + int dist=0; + for (int i= g.getIndexOf(A); i<= g.getIndexOf(F); i++){ + dist += dj.distance[i]; + } + System.out.println("Distance between "+A+"---"+F+"---is --"+dist); + + dj.bellmanFordAlgo(g, C); + dist=0; + for (int i= g.getIndexOf(C); i<= g.getIndexOf(F); i++){ + dist += dj.distance[i]; + } + System.out.println("Distance BellMan ford between "+C+"---"+F+"---is --"+dist); + } +} diff --git a/DirectedCycle.java b/DirectedCycle.java new file mode 100644 index 0000000..00f1201 --- /dev/null +++ b/DirectedCycle.java @@ -0,0 +1,92 @@ +package com.program.graph.algo; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +public class DirectedCycle { + + private DiGraph.Vertex [] edgeTo; + private Stack cyclePath; + private boolean onStack[]; + + public DirectedCycle(DiGraph g){ + int size = g.getVertices().size(); + onStack = new boolean[size]; + edgeTo = new DiGraph.Vertex[size]; + + for (DiGraph.Vertex v : g.getVertices()) { + if (!v.isVisited()) { + dfs(g, v);//, v); + } + } + } + + public void dfs(DiGraph g, DiGraph.Vertex v) {//, DiGraph.Vertex prev){ + v.setVisited(true); + onStack[g.getIndexOf(v)] = true; + + for (DiGraph.Edge e : v.getEdges()) { + DiGraph.Vertex w = e.getTo(); + if (this.hashCycle()) { + return; + }else if (!w.isVisited()) { + edgeTo[g.getIndexOf(w)] = v; + dfs(g, w);//, v); + } else if ( onStack[g.getIndexOf(w)]) { // cycle has found + cyclePath = new Stack(); + //cycle path from source w to target v. + for (DiGraph.Vertex x = v; x != w; x = edgeTo[g.getIndexOf(x)]) { + cyclePath.push(x); + } + cyclePath.push(w); + cyclePath.push(v); // coz cycle will end again at v + } + onStack[g.getIndexOf(v)]=false; // once a vertex has visited completely it must be set to false, means its all edges has been visited; + } + } + + public boolean hashCycle() { + return cyclePath != null; + } + + public Stack getCyclePath(){ + return cyclePath; + } + public static void main(String[] args) { + List vertices = new ArrayList(); + DiGraph.Vertex A = new DiGraph.Vertex("A"); + DiGraph.Vertex B = new DiGraph.Vertex("B"); + DiGraph.Vertex C = new DiGraph.Vertex("C"); + DiGraph.Vertex D = new DiGraph.Vertex("D"); + DiGraph.Vertex E = new DiGraph.Vertex("E"); + DiGraph.Vertex F = new DiGraph.Vertex("F"); + DiGraph.Vertex G = new DiGraph.Vertex("G"); + DiGraph.Vertex H = new DiGraph.Vertex("H"); + vertices.add(A); + vertices.add(B); + vertices.add(C); + vertices.add(D); + vertices.add(E); + vertices.add(F); + vertices.add(G); + vertices.add(H); + + List edges = new ArrayList(); + edges.add(new DiGraph.Edge(0,A,B)); + edges.add(new DiGraph.Edge(0,B,C)); + edges.add(new DiGraph.Edge(0,H,B)); + edges.add(new DiGraph.Edge(0,C,D)); + edges.add(new DiGraph.Edge(0,C,E)); + edges.add(new DiGraph.Edge(0,E,H)); + edges.add(new DiGraph.Edge(0,E,F)); + edges.add(new DiGraph.Edge(0,E,G)); + + DiGraph g = new DiGraph(DiGraph.TYPE.DIRECTED, vertices, edges); + DirectedCycle dc = new DirectedCycle(g); + for (DiGraph.Vertex v : dc.getCyclePath()){ + System.out.println("-"+v); + } + } + +} diff --git a/Graph.java b/Graph.java index 8e885a8..1f6f4ea 100644 --- a/Graph.java +++ b/Graph.java @@ -1,251 +1,251 @@ -package com.test.graph.algo; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; - -/* - * @author rrohit - */ -public class Graph { - - private List vertices = new CopyOnWriteArrayList(); - private List edges = new CopyOnWriteArrayList(); - private TYPE type = TYPE.UNDIRECTED; - - public enum TYPE { - DIRECTED, UNDIRECTED; - } - - public Graph(TYPE type){ - this.type = type; - } - - public Graph (List vertices, List edges) { - this(TYPE.UNDIRECTED, vertices, edges); - } - - public Graph(TYPE type, List vertices, List edges){ - this(type); - this.vertices.addAll(vertices); - this.edges.addAll(edges); - - /* - * Now construct graph with the help of the above vertices and edges - */ - - for (Edge e : edges) { - Vertex from = e.from; - Vertex to = e.to; - - if (!this.vertices.contains(from) || !this.vertices.contains(to)) { - continue; - } - - //get from and to vertex from list of Vertices using from and to in the respective edge - int index = vertices.indexOf(from); - Vertex fromVertex = this.vertices.get(index); - index = vertices.indexOf(to); - Vertex toVertex = this.vertices.get(index); - - fromVertex.edges.add(e); // fromVertex.addEdge(e); - - if (this.type == TYPE.UNDIRECTED) { - // add reciprocal edge also i.e A-->B and B-->A is reciprocal - Edge reciprocal = new Edge(e.cost, toVertex, fromVertex); - toVertex.edges.add(reciprocal); // toVertex.addEdge(reciprocal) - this.edges.add(reciprocal); - } - } - } - - /* - * return index of the given vertex from the list of vertex, vertices - */ - public int getIndexOf(Vertex v){ - return this.vertices.indexOf(v); - } - - /* - * Deep copy of a graph from another graph - */ - public Graph(Graph g){ - /* - * Copy the vertices which copies edges - */ - for (Vertex v : g.vertices) { - this.vertices.add(new Vertex(v)); - } - /* - * update the object references i.e update edges - */ - for (Vertex v : this.vertices){ - for (Edge e : v.edges) { - Vertex from = e.getFrom(); - Vertex to = e.getTo(); - int index = this.vertices.indexOf(from); - e.from = this.vertices.get(index); - index = this.vertices.indexOf(to); - e.to = this.vertices.get(index); - this.edges.add(e); - } - } - - } - - - public List getVertices() { - return vertices; - } - - public void setVertices(List vertices) { - this.vertices = vertices; - } - - public List getEdges() { - return edges; - } - - public void setEdges(List edges) { - this.edges = edges; - } - - public TYPE getType() { - return type; - } - - public void setType(TYPE type) { - this.type = type; - } - - - static class Vertex { - - private char label; - private int weight; - public boolean visited; - private List edges = new ArrayList(); - - public Vertex(char label){ - this.label = label; - weight=0; - visited=false; - } - - public Vertex(Vertex v){ - this(v.label); - for (Edge e : v.edges) { - this.edges.add(new Edge(e)); - } - } - - /* - * Find path from A to B, means fromVertex is A and toVertex is B - */ - private boolean pathTo(Vertex v){ - for (Edge e : edges) { - if (e.to.equals(v)) { - return true; - } - } - return false; - } - - public boolean equals(Object obj){ - if(!(obj instanceof Vertex)){ - return false; - } - - Vertex v = (Vertex) obj; - if (v.label != this.label){ - return false; - } - - if (v.weight != this.weight){ - return false; - } - return true; - } - - public String toString(){ - return "["+this.label+"]"; - } - - public char getLabel() { - return label; - } - - public void setLabel(char label) { - this.label = label; - } - - public int getWeight() { - return weight; - } - - public void setWeight(int weight) { - this.weight = weight; - } - - public List getEdges() { - return edges; - } - - public void setEdges(List edges) { - this.edges = edges; - } - - public boolean isVisited() { - return visited; - } - - public void setVisited(boolean visited) { - this.visited = visited; - } - - } - - - static class Edge{ - - private Vertex from; - private Vertex to; - private int cost; - - public Edge(int cost, Vertex from, Vertex to){ - this.from = from; - this.to = to; - this.cost=cost; - } - - public Edge(Edge e){ - this(e.cost, e.from, e.to); - } - - public Vertex getFrom() { - return from; - } - - public void setFrom(Vertex from) { - this.from = from; - } - - public Vertex getTo() { - return to; - } - - public void setTo(Vertex to) { - this.to = to; - } - - public int getCost() { - return cost; - } - - public void setCost(int cost) { - this.cost = cost; - } - - } - -} +package com.program.graph.algo; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +/* + * @author rrohit + */ +public class Graph { + + private List vertices = new CopyOnWriteArrayList(); + private List edges = new CopyOnWriteArrayList(); + private TYPE type = TYPE.UNDIRECTED; + + public enum TYPE { + DIRECTED, UNDIRECTED; + } + + public Graph(TYPE type){ + this.type = type; + } + + public Graph (List vertices, List edges) { + this(TYPE.UNDIRECTED, vertices, edges); + } + + public Graph(TYPE type, List vertices, List edges){ + this(type); + this.vertices.addAll(vertices); + this.edges.addAll(edges); + + /* + * Now construct graph with the help of the above vertices and edges + */ + + for (Edge e : edges) { + Vertex from = e.from; + Vertex to = e.to; + + if (!this.vertices.contains(from) || !this.vertices.contains(to)) { + continue; + } + + //get from and to vertex from list of Vertices using from and to in the respective edge + int index = vertices.indexOf(from); + Vertex fromVertex = this.vertices.get(index); + index = vertices.indexOf(to); + Vertex toVertex = this.vertices.get(index); + + fromVertex.edges.add(e); // fromVertex.addEdge(e); + + if (this.type == TYPE.UNDIRECTED) { + // add reciprocal edge also i.e A-->B and B-->A is reciprocal + Edge reciprocal = new Edge(e.cost, toVertex, fromVertex); + toVertex.edges.add(reciprocal); // toVertex.addEdge(reciprocal) + this.edges.add(reciprocal); + } + } + } + + /* + * return index of the given vertex from the list of vertex, vertices + */ + public int getIndexOf(Vertex v){ + return this.vertices.indexOf(v); + } + + /* + * Deep copy of a graph from another graph + */ + public Graph(Graph g){ + /* + * Copy the vertices which copies edges + */ + for (Vertex v : g.vertices) { + this.vertices.add(new Vertex(v)); + } + /* + * update the object references i.e update edges + */ + for (Vertex v : this.vertices){ + for (Edge e : v.edges) { + Vertex from = e.getFrom(); + Vertex to = e.getTo(); + int index = this.vertices.indexOf(from); + e.from = this.vertices.get(index); + index = this.vertices.indexOf(to); + e.to = this.vertices.get(index); + this.edges.add(e); + } + } + + } + + + public List getVertices() { + return vertices; + } + + public void setVertices(List vertices) { + this.vertices = vertices; + } + + public List getEdges() { + return edges; + } + + public void setEdges(List edges) { + this.edges = edges; + } + + public TYPE getType() { + return type; + } + + public void setType(TYPE type) { + this.type = type; + } + + + public static class Vertex { + + private char label; + private int weight; + public boolean visited; + private List edges = new ArrayList(); + + public Vertex(char label){ + this.label = label; + weight=0; + visited=false; + } + + public Vertex(Vertex v){ + this(v.label); + for (Edge e : v.edges) { + this.edges.add(new Edge(e)); + } + } + + /* + * Find path from A to B, means fromVertex is A and toVertex is B + */ + private boolean pathTo(Vertex v){ + for (Edge e : edges) { + if (e.to.equals(v)) { + return true; + } + } + return false; + } + + public boolean equals(Object obj){ + if(!(obj instanceof Vertex)){ + return false; + } + + Vertex v = (Vertex) obj; + if (v.label != this.label){ + return false; + } + + if (v.weight != this.weight){ + return false; + } + return true; + } + + public String toString(){ + return "["+this.label+"]"; + } + + public char getLabel() { + return label; + } + + public void setLabel(char label) { + this.label = label; + } + + public int getWeight() { + return weight; + } + + public void setWeight(int weight) { + this.weight = weight; + } + + public List getEdges() { + return edges; + } + + public void setEdges(List edges) { + this.edges = edges; + } + + public boolean isVisited() { + return visited; + } + + public void setVisited(boolean visited) { + this.visited = visited; + } + + } + + + public static class Edge { + + private Vertex from; + private Vertex to; + private int cost; + + public Edge(int cost, Vertex from, Vertex to){ + this.from = from; + this.to = to; + this.cost=cost; + } + + public Edge(Edge e){ + this(e.cost, e.from, e.to); + } + + public Vertex getFrom() { + return from; + } + + public void setFrom(Vertex from) { + this.from = from; + } + + public Vertex getTo() { + return to; + } + + public void setTo(Vertex to) { + this.to = to; + } + + public int getCost() { + return cost; + } + + public void setCost(int cost) { + this.cost = cost; + } + + } + +} diff --git a/SymbolGraph.java b/SymbolGraph.java new file mode 100644 index 0000000..79957e9 --- /dev/null +++ b/SymbolGraph.java @@ -0,0 +1,66 @@ +package com.program.graph.algo; + +import java.io.File; +import java.io.FileNotFoundException; +import java.util.ArrayList; +import java.util.List; +import java.util.Scanner; + +public class SymbolGraph { + Graph1 g; + public SymbolGraph(String fileName, String delim) throws FileNotFoundException { + + g = new Graph1(Graph1.TYPE.UNDIRECTED); + + /*FileInputStream fis = new FileInputStream(fileName); + InputStreamReader in = new InputStreamReader(fis);*/ + Scanner in = new Scanner(new File(fileName)); + //BufferedReader reader = new BufferedReader(new FileReader(fileName)); + List vertices = new ArrayList(); + List edges = new ArrayList(); + int index; + + while (in.hasNextLine()) { + + String [] input = in.nextLine().split(delim); + Graph1.Vertex fromVertex, toVertex; + fromVertex = new Graph1.Vertex(input[0]); + vertices.add(fromVertex); + + for (int i=1; i queue = new ArrayBlockingQueue(g.vertexCount); + int counter = 0; + // add all vertex with indegree 0 in queue + for (DiGraph.Vertex v : g.getVertices()) { + if (inDegree[g.getIndexOf(v)] == 0) { + queue.add(v); + } + } + + DiGraph.Vertex v,w; + while (!queue.isEmpty()) { + v = queue.remove(); + topologicalOrder[counter++] = v; + System.out.println("--"+v); + for (DiGraph.Edge e : v.getEdges()) { // for each w adjacent to v + w = e.getTo(); + if ( --inDegree[g.getIndexOf(w)] == 0) { + // decrease indegree of each vertex once visited by 1 and add to queue if indegree becomes 0 + queue.add(w); + } + } + } + if (counter != g.vertexCount) { + System.out.println("graph has cycle"); + } + } + + public static void main(String[] args) { + List vertices = new ArrayList(); + DiGraph.Vertex A = new DiGraph.Vertex("A"); + /* + * If Inner class graph and edge were not static then + * First we have to instantiate Graph and then vertex/edge + * eg : + * Grapg g1 = new Graph(); + * Graph.vertex A = g1.new Vertex('A'); + * + */ + DiGraph.Vertex B = new DiGraph.Vertex("B"); + DiGraph.Vertex C = new DiGraph.Vertex("C"); + DiGraph.Vertex D = new DiGraph.Vertex("D"); + DiGraph.Vertex E = new DiGraph.Vertex("E"); + DiGraph.Vertex F = new DiGraph.Vertex("F"); + DiGraph.Vertex G = new DiGraph.Vertex("G"); + DiGraph.Vertex H = new DiGraph.Vertex("H"); + vertices.add(A); + vertices.add(B); + vertices.add(C); + vertices.add(D); + vertices.add(E); + vertices.add(F); + vertices.add(G); + vertices.add(H); + + List edges = new ArrayList(); + edges.add(new DiGraph.Edge(0,A,B)); + edges.add(new DiGraph.Edge(0,B,C)); + edges.add(new DiGraph.Edge(0,B,H)); + edges.add(new DiGraph.Edge(0,C,D)); + edges.add(new DiGraph.Edge(0,C,E)); + edges.add(new DiGraph.Edge(0,E,H)); + edges.add(new DiGraph.Edge(0,E,F)); + edges.add(new DiGraph.Edge(0,E,G)); + + DiGraph g = new DiGraph(DiGraph.TYPE.DIRECTED, vertices, edges); + TopologicalSort tp = new TopologicalSort(g); + for (DiGraph.Vertex v : tp.topologicalOrder) { + System.out.println("--"+v); + } + } + +} diff --git a/TwoColor.java b/TwoColor.java new file mode 100644 index 0000000..3fbe45d --- /dev/null +++ b/TwoColor.java @@ -0,0 +1,100 @@ +package com.program.graph.algo; + +import java.util.ArrayList; +import java.util.List; + +public class TwoColor { + private boolean[] color; + private boolean isTwoColorable = true; + + public TwoColor(Graph g){ + color = new boolean[g.getVertices().size()]; + for (Graph.Vertex v : g.getVertices()) { + if (!v.visited) { + dfs(g, v); + } + } + } + public void printColor(){ + + for (boolean val : color) { + System.out.print("--"+val); + } + } + + public void dfs(Graph g, Graph.Vertex v){ + v.visited = true; + Graph.Vertex w; + for (Graph.Edge e : v.getEdges()) { + w = e.getTo(); + if (!w.visited) { + color[g.getIndexOf(w)] = !color[g.getIndexOf(v)]; + dfs(g, w); + } else if (color[g.getIndexOf(w)] == color[g.getIndexOf(v)]) { + isTwoColorable = false; + } + } + } + + public boolean isBipartite(){ + return isTwoColorable; + } + + public static void main(String[] args) { + List vertices = new ArrayList(); + Graph.Vertex A = new Graph.Vertex('A'); + /* + * If Inner class graph and edge were not static then + * First we have to instantiate Graph and then vertex/edge + * eg : + * Grapg g1 = new Graph(); + * Graph.vertex A = g1.new Vertex('A'); + * + */ + Graph.Vertex B = new Graph.Vertex('B'); + Graph.Vertex C = new Graph.Vertex('C'); + Graph.Vertex D = new Graph.Vertex('D'); + Graph.Vertex E = new Graph.Vertex('E'); + Graph.Vertex F = new Graph.Vertex('F'); + Graph.Vertex G = new Graph.Vertex('G'); + Graph.Vertex H = new Graph.Vertex('H'); + Graph.Vertex I = new Graph.Vertex('I'); + Graph.Vertex J = new Graph.Vertex('J'); + Graph.Vertex K = new Graph.Vertex('K'); + Graph.Vertex L = new Graph.Vertex('L'); + vertices.add(A); + vertices.add(B); + vertices.add(C); + vertices.add(D); + vertices.add(E); + vertices.add(F); + vertices.add(G); + vertices.add(H); + vertices.add(I); + vertices.add(J); + vertices.add(K); + vertices.add(L); + + List edges = new ArrayList(); + edges.add(new Graph.Edge(0,A,B)); + edges.add(new Graph.Edge(0,B,C)); + edges.add(new Graph.Edge(0,B,H)); + edges.add(new Graph.Edge(0,C,D)); + edges.add(new Graph.Edge(0,C,E)); + edges.add(new Graph.Edge(0,E,H)); + edges.add(new Graph.Edge(0,E,F)); + edges.add(new Graph.Edge(0,E,G)); + + edges.add(new Graph.Edge(0,I,J)); + edges.add(new Graph.Edge(0,J,K)); + edges.add(new Graph.Edge(0,I,L)); + edges.add(new Graph.Edge(0,I,K)); + + + Graph g = new Graph(vertices, edges); + TwoColor tc = new TwoColor(g); + System.out.println("Is graph Bipartite :: "+tc.isBipartite()); + System.out.println("---PRINT COLOR---"); + tc.printColor(); + } +}