I am implementing depth first traversal of a graph drawn by the user using jung.
I have following code at this moment:
public <V,E> void dftdraw(Graph<V,E> g) {
V start = null;
for (V v:g.getVertices()){
if(v.toString().equals("0"))
start = v;
}
Set visited = new HashSet();
LinkedList stack = new LinkedList();
stack.add(start);
System.out.println(start.toString());
// traverse through graph in depth-first order
while (!stack.isEmpty())
{
V v = (V)stack.removeFirst();
visited.add(v);
Set neighbors = (Set) g.getNeighbors(v);
for (Iterator n_it = neighbors.iterator(); n_it.hasNext(); )
{
V w = (V)n_it.next();
if (!visited.contains(w)){
System.out.println(w.toString());
stack.addFirst(w);
}
}
}
}
But this is not doing depth first, it's first printing out the vertices connected to the starting vertex, and not like, traversing first connected vertex, then traversing through it's connected vertices.
That's because you're printing the vertex too soon. If you want them printed in the visiting order, you need to print at the time you're visiting (after you remove the vertex from stack). Otherwise the algorithm seems OK.
So , now I am doing Depth first traversal , by recursion using the following code :
public <V, E> void dftdraw(Graph<V, E> g) {
V start = null;
for (V v : g.getVertices()) {
if (v.toString().equals(jTextField2.getText())) {
start = v;
}
}
if(!visiteddfs.contains(start)) {
dfspath(g,start);
}
for(int i=0;i<l2.size();i++){
jTextField4.setText(jTextField4.getText() + " " + l2.get(i));
}
}
public <V,E> void dfspath(Graph<V,E> g,V v){
visiteddfs.add(v);
l2.add(v);
Set neighbors = (Set) g.getNeighbors(v);
//System.out.println(v);
for (Iterator n_it = neighbors.iterator(); n_it.hasNext();) {
V w = (V) n_it.next();
if(!visiteddfs.contains(w)){
dfspath(g,w);
}
}
finisheddfs.add(v);
}
and with slight modifications , the code posted in the question is used for breadth first traversal . Here's the code for that :
public <V, E> void bstdraw(Graph<V, E> g) {
V start = null;
for (V v : g.getVertices()) {
if (v.toString().equals(jTextField1.getText())) {
start = v;
}
}
Set visited = new HashSet();
LinkedList stack = new LinkedList();
stack.add(start);
visited.add(start);
l.add(start);
// traverse through graph in depth-first order
while (!stack.isEmpty()) {
V v = (V) stack.removeFirst();
Set neighbors = (Set) g.getNeighbors(v);
//System.out.println(v);
for (Iterator n_it = neighbors.iterator(); n_it.hasNext();) {
V w = (V) n_it.next();
if (!visited.contains(w)) {
l.add(w);
g2.addEdge("edge" + w, (Integer) v, (Integer) w);
jPanel4.repaint();
jPanel4.updateUI();
visited.add(w);
stack.addLast(w);
}
}
}
for (int i = 0; i < l.size(); i++) {
jTextField3.setText(jTextField3.getText() + " " + l.get(i));
}
}
Related
Given a directed graph, the task is to do Breadth First Traversal of this graph starting from 0.
Complete the Function bfsOfGraph() to return Breadth First Traversal of given graph.
Here, V denotes the number of vertices.
Here's the problem link
class Solution
{
public ArrayList<Integer> bfsOfGraph(int V , ArrayList<ArrayList<Integer>> adj)
{
ArrayList<Integer> bfs = new ArrayList<>();
boolean vis[] = new boolean[V+1];
for( int i = 1; i < V+1 ; i++){
if(vis[i] == false){
Queue<Integer> q = new LinkedList<>();
q.add(i);
vis[i] = true;
while(!q.isEmpty()){
Integer node = q.poll();
bfs.add(node);
for(Integer it : adj.get(node)){
if(vis[it] == false){
vis[it] = true;
q.add(it);
}
}
}
}
}
return bfs;
}
}
When you know you have started (origin of the graph) from 0 then why are calling on each node (vertex) of the graph. I think you misunderstood the questions. You have to apply BFS on the Origin 0. You Might get the IndexOutOfBound Exception as well because all the vertex of the graphs is from 0 to V-1 inclusive. I can see you are treating the graph vertex as 1 to V inclusive.
public ArrayList<Integer> bfsOfGraph(int V,ArrayList<ArrayList<Integer>> adj)
{
Queue<Integer> queue = new LinkedList<>();
boolean visited[] = new boolean[V];
ArrayList<Integer> results = new ArrayList<>();
queue.add(0);
while(!queue.isEmpty()){
Integer nextNode = queue.poll();
results.add(nextNode);
visited[nextNode] = true;
if(adj.get(nextNode) != null){
for(int neighbor : adj.get(nextNode)){
if(!visited[neighbor]){
queue.add(neighbor);
visited[neighbor] = true;
}
}
}
}
return results;
}
Below is my bfs algorithm, the algorithm works and finds the node given the start and target. But I want to save edges for the used path in a linkedList to draw the path.
My BFS:
public DGPath breadthFirstSearch(String startId, String targetId) {
V start = this.getVertexById(startId);
V target = this.getVertexById(targetId);
if (start == null || target == null) return null;
DGPath path = new DGPath();
path.start = start;
path.visited.add(start);
// easy target
if (start == target) return path;
// TODO calculate the path from start to target by breadth-first-search
// register all visited vertices while going, for statistical purposes
// if you hit the target: complete the path and bail out !!!
Queue<V> fifoQueue = new LinkedList<>();
Map<V,V> visitedFrom = new HashMap<>();
fifoQueue.offer(start);
visitedFrom.put(start, null);
while (!fifoQueue.isEmpty()) {
V current = fifoQueue.poll();
for (E e : current.getEdges()) {
V neighbour = e.getTo();
path.visited.add(neighbour);
if (neighbour == target) {
while (current != null) {
path.getEdges().addFirst(e);
current = visitedFrom.get(current);
}
return path;
} else if (!visitedFrom.containsKey(neighbour)) {
visitedFrom.put(neighbour,current);
fifoQueue.offer(neighbour);
}
}
}
// no path found, graph was not connected ???
return null;
}
The DGPath is the class that creates the path as shown below:
public class DGPath {
private V start = null;
private LinkedList<E> edges = new LinkedList<>();
private double totalWeight = 0.0;
private Set<V> visited = new HashSet<>();
/**
* representation invariants:
* 1. The edges are connected by vertices, i.e. FOR ALL i: 0 < i < edges.length: edges[i].from == edges[i-1].to
* 2. The path begins at vertex == start
* 3. if edges is empty, the path also ends at vertex == start
* otherwise edges[0].from == start and the path continues along edges[i].to for all 0 <= i < edges.length
**/
#Override
public String toString() {
StringBuilder sb = new StringBuilder(
String.format("Weight=%f Length=%d Visited=%d (",
this.totalWeight, 1 + this.edges.size(), this.visited.size()));
sb.append(start.getId());
for (E e : edges) {
sb.append(", " + e.getTo().getId());
}
sb.append(")");
return sb.toString();
}
public V getStart() {
return start;
}
public LinkedList<E> getEdges() {
return edges;
}
public double getTotalWeight() {
return totalWeight;
}
public Set<V> getVisited() {
return visited;
}
}
I want to save the right edges in de linkedlist edges from the BGPath class (called path in my BFS algo method). So I already saved the used vertices in a map to go back to the root. But when I add the edge to the path it just saves the last edge used multiple times.. The problem is the vertex can have multiple edges, so I need to add the edge from the previous that was pointing to the last "current" until I'm back to the root. But I cant wrap my head around the right way to do this.
The line where I now add the edge to the list of edges is: path.getEdges().add(e)
I think, your problem is the same line, where your are adding the edges, that line is adding the same edge in inner while loop again and again, so you are only traversing back but not adding those nodes to your edges list.
I think, it should be like this
while (!fifoQueue.isEmpty()) {
V current = fifoQueue.poll();
for (E e : current.getEdges()) {
V neighbour = e.getTo();
path.visited.add(neighbour);
if (neighbour == target) {
path.getEdges().addFirst(e):
while (current != null) {
path.getEdges().addFirst(current) ;
current = visitedFrom.get(current);
}
return path;
} else if (!visitedFrom.containsKey(neighbour)) {
visitedFrom.put(neighbour,current);
fifoQueue.offer(neighbour);
}
}
}
// no path found, graph was not connected ???
return null;
}
I am implementing the code for cycle detection in undirected graph using find/union methods of disjointsets.
Here is the implementation:
public boolean isCyclicundirected(){
int k;
ArrayDisjointSet set = new ArrayDisjointSet(5);
//Set<Vertex> parents = new HashSet<Vertex>();
System.out.println(vertexMap);
Set<String> allVertices = vertexMap.keySet();
for (String v : allVertices){
Iterator<Edge> e = vertexMap.get(v).adj.iterator();
while (e.hasNext()){
int i = Integer.parseInt(vertexMap.get(v).name);
int j = Integer.parseInt(e.next().target.name);
if (set.isConnected(i, j))
return true;
else
k = set.join(i, j);
System.out.println(set);
}
}
return false;
}
and here is the isConnected of disjoinset
public boolean isConnected(int i, int j){
return find(i)==find(j);
}
if two nodes have the same root, (returned by find), that indicates there is a cycle.
For a graph like this which has no cycles (1,2),(2,3),(3,4), my method returns true.
I am failing to understand what is wrong.
EDIT latest: After suggestions below:
public boolean isCyclicundirected() {
int k;
HashSet<HashSet<Vertex>> vertexpairs = new HashSet<HashSet<Vertex>>();
ArrayDisjointSet set = new ArrayDisjointSet(100);
Set<String> allVertices = vertexMap.keySet();
for (String v : allVertices) {
Vertex current = vertexMap.get(v);
for (Edge e : current.adj){
Vertex nextVertex = e.target;
HashSet<Vertex> temp = new HashSet<Vertex>();
temp.add(nextVertex);
temp.add(current);
if (!vertexpairs.contains(temp)) {
vertexpairs.add(temp);
int i = Integer.parseInt(current.name);
int j = Integer.parseInt(nextVertex.name);
if (set.isConnected(i, j))
return true;
else
k = set.join(i, j);
System.out.println(set);
}
}
}
return false;
}
I get node:java.util.NoSuchElementException
You iterate over each edge twice, once from each side. You need to only consider any edge once.
I am fairly new to java and I have been struggling with this exercise for two weeks now(It's an homework exercise in my school). I need to create a topological sort and print out all of the possible connections. I have read a lot about topological sorting now, but we have this certain line of code that we have to work with. I'm pretty sure I could do the topological sorting when I have the list of vertices. My problem is, I don't know how to list all of the vertices from this given code. Could anyone give me some tips or leads or perhaps an example, I would really really appreciate it.
Here is the given code we need to work with:
import java.util.*;
public class Answer {
public static void main (String[] args) {
Answer a = new Answer();
a.run();
}
public void run() {
// TODO!!! YOUR TESTS HERE!
Graph g = new Graph ("G");
Vertex a = new Vertex ("A");
Vertex b = new Vertex ("B");
Vertex c = new Vertex ("C");
g.first = a;
a.next = b;
b.next = c;
Edge ab = new Edge ("AB");
Edge ac = new Edge ("AC");
Edge ba = new Edge ("BA");
Edge ca = new Edge ("CA");
a.first = ab;
b.first = ba;
c.first = ca;
ab.next = ac;
ab.target = b;
ac.target = c;
ba.target = a;
ca.target = a;
System.out.println (g);
}
class Vertex {
String id;
Vertex next;
Edge first;
Vertex (String s, Vertex v, Edge e) {
id = s;
next = v;
first = e;
}
Vertex (String s) {
this (s, null, null);
}
#Override
public String toString() {
return id;
}
// TODO!!! Your Vertex methods here!
} // Vertex
class Edge {
String id;
Vertex target;
Edge next;
Edge (String s, Vertex v, Edge e) {
id = s;
target = v;
next = e;
}
Edge (String s) {
this (s, null, null);
}
#Override
public String toString() {
return id;
}
// TODO!!! Your Edge methods here!
} // Edge
class Graph {
String id;
Vertex first;
Graph (String s, Vertex v) {
id = s;
first = v;
}
Graph (String s) {
this (s, null);
}
#Override
public String toString() {
String nl = System.getProperty ("line.separator");
StringBuffer sb = new StringBuffer (nl);
sb.append (id + nl);
Vertex v = first;
while (v != null) {
sb.append (v.toString() + " --> ");
Edge e = v.first;
while (e != null) {
sb.append (e.toString());
sb.append ("(" + v.toString() + "->"
+ e.target.toString() + ") ");
e = e.next;
}
sb.append (nl);
v = v.next;
}
return sb.toString();
}
// TODO!!! Your Graph methods here!
} // Graph
}
Apparently, the graph has a reference to the first vertex, and the vertices themselves are linked together into a singly linked list. This code should be all you need to collect the vertices into a Java list:
public List<Vertex> allVertices(Graph g) {
final List<Vertex> vertices = new ArrayList<>();
for (Vertex v = g.first; v != null; v = v.next)
vertices.add(v);
return vertices;
}
I would suggest that you add a "lastvisited" integer field to the edge which is set to zero, or use a boolean "visited"(true/false). Then start at one vertex. Assuming the graph is connected, you will reach all vertexes by going over the unvisited edges for one vertex, then following the edges to the vertex it leads to, marking the edge as followed, and calling your count function for this vertex recursively.
I.E.: count(node) = sum(my unvisited edges) mark_edge_as_visited(edge), count(edge.target)
Please note that you also have to consider that the graph appears to be a directed graph, so an edge leading from a to b and from b to a is counted as two edges.
Edit: I made a mistake, you also need to mark the vertex as visited, or it will be visited twice (I was thinking of an undirected graph).
Preface: I know that there are high quality graph APIs available. I'm interested in writing my own for self-improvement.
This is my function to add nodes:
public void addNode(Vertex v, Collection<Edge> neighbors) {
int originalSize = size();
if (head == null) {
head = v;
}
else {
Collection<Edge> inEdges = new ArrayList<Edge>();
inEdges.addAll(neighbors);
traverseGraphToAdd(head, inEdges, v);
}
assert originalSize + 1 == size() :
String.format("adding operation failed. original size: %d, current size: %d", originalSize, size());
}
private void traverseGraphToAdd(Vertex start, Collection<Edge> inEdges, Vertex toAdd) {
Iterator<Edge> iter = inEdges.iterator();
Edge e;
while (iter.hasNext()) {
e = iter.next();
if (e.getSource().equals(start)) {
start.addEdge(e);
iter.remove();
}
else if (! directionalEdges && e.getSink().equals(start)) {
start.addEdge(e);
iter.remove();
}
}
if (inEdges.size() > 0) { //otherwise there's no point in continuing to search
for (Edge arc : start.getOutEdges()) {
traverseGraphToAdd(arc.getSink(), inEdges, toAdd);
}
}
}
Size and its dependencies:
public int size() {
int count = 0;
if (head == null) {
return 0;
}
else {
count = countNodes(head);
}
clearVisited();
return count;
}
private int countNodes(Vertex start) {
int result = 1;
start.setVisited(true);
for (Edge e: start.getOutEdges()) {
if (! e.getSink().isVisited()) {
result += countNodes(e.getSink());
}
}
return result;
}
private void clearVisited() {
if (head != null) {
clearNode(head);
}
}
private void clearNode(Vertex start) {
start.setVisited(false);
for (Edge e: start.getOutEdges()) {
if (e.getSink().isVisited()) {
clearNode(e.getSink());
}
}
}
The Edge class:
public Edge(Vertex source, Vertex sink, int weight) {
this.source = source;
this.sink = sink;
this.weight = weight;
}
The following call works:
g.addNode(ftw, new HashSet<Edge>()); //first node - empty edges
g.addNode(odp, Arrays.asList(new Edge(ftw, odp, 3))); //link new node to one already in the graph
This does not:
g.addNode(tlt, Arrays.asList(new Edge(tlt, ftw, 2)));
In this one, the first argument of the Edge constructor is not the node already in the graph. I try to rectify this in addNode with the following (repeated from above):
if (e.getSource().equals(start)) { /*... */ }
else if (! directionalEdges && e.getSink().equals(start)) { /*... */ }
directionalEdges is a class field that determines whether or not this graph is directional or not.
However, this causes assertion errors:
Exception in thread "main" java.lang.AssertionError: adding operation failed. original size: 1, current size: 1
What is going on here?
The graph you're trying to create in your example looks like this:
tlt -> ftw -> odp
After creating ftw -> odp, you should (and do, I believe) have head == ftw. After adding tlt, you should have head == tlt if you want your traversal algorithm to work properly. But in the code you've shown us, there is only one place where head is assigned to, and that happens only in the condition when head == null, in the fifth line of addNode(). Therefore, head doesn't change when you add tlt, and so traverseGraphToAdd() therefore starts form ftw instead of tlt as you intend for it to.
You have a more general problem here, however, namely that your code isn't able to handle directed graphs which aren't rooted (that is, they have more than one source node.) Consider what would happen if you wanted a graph like this one:
a -> b <- c
I think you'd have a problem with this, since you no longer have a single head.