Breadth First Search: How many states of a vertex are needed? - java

I am working on Breadth First Search and I tried to write BFS to print all the edges. The first version is adapted from Algorithm book in which a vertex has 3 states: NOT_VISIT (initial state), VISIT and PROCESSED. A vertex is 'VISIT' when you first see it. A vertex is 'PROCESSED' when all of its neighbors are visited. The second version is the one that I wrote, use only 2 states: Initial state and VISITED. Both work:
public static void BFS(Graph g, int start) {
boolean[] visit = new boolean[g.size()];
boolean[] process = new boolean[g.size()];
List<Integer> queue = new ArrayList<Integer>();
queue.add(start);
visit[start] = true;
while (!queue.isEmpty()) {
int currentVertex = queue.remove(0);
process[currentVertex] = true;
List<Integer> adj = g.getAdjacents(currentVertex);
if (adj != null) {
for (Integer i : adj) {
if (visit[i] == false) {
visit[i] = true;
queue.add(i);
}
if (process[i] == false) {
System.out.println(currentVertex + " --- "
+ i);
}
}
}
}
}
public static int BFS2(Graph g, int start) {
List<Integer> queue = new ArrayList<Integer>();
boolean[] visited = new boolean[g.size()];
queue.add(start);
while (!queue.isEmpty()) {
int v = queue.remove(0);
visited[v] = true;// only mark visited[v] = true when processing all
// its neighbors
List<Integer> adj = g.getAdjacents(v);
if (adj != null) {
for (Integer i : adj) {
if (!visited[i]) {
queue.add(i);
System.out.println(v + " --- "
+ i);
}
}
}
}
}
My question is: When is it necessary to have 3 states for a vertex in BFS ? Can you give an example when we need 3 states ?

Usually you add the middle state ("Visit" in your case, commonly "Gray" when using colors to mark nodes) just to visualise how BFS is working. In standard implementation it is not necessary (you may switch to "Visited" without going through the middle state.)
You can see it yourself, try to follow BFS (even with paper and pencil you can do it). You will see that nodes in state "Visit" are equally distanced from source (with maximum difference of 1, to be specific). For educational purposes it is good to do the same with DFS then (so you can observe the difference between Breadth-First and Depth-First searching).

Related

I am trying to do BFS search but get Runtime Error Index out Of Bounds Exception

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;
}

Saving the edges traversed in breadth first search Java

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;
}

Depth First Search on graph using Iterator

I'm trying to make this into a Depth First Search. At first it was in Breadth First and now I'm trying to convert it. I've been working on this for DAYS and have tried multiple different things.
import java.util.*;
class Graph{
class Edge{
int v,w;
public Edge(int v,int w){
this.v=v; this.w=w;
}
#Override
public String toString(){
return "("+v+","+w+")";
}
}
List<Edge> G[];
public Graph(int n){
G=new LinkedList[n];
for(int i=0;i<G.length;i++)
G[i]=new LinkedList<Edge>();
}
boolean isConnected(int u,int v){
for(Edge i: G[u])
if(i.v==v) return true;
return false;
}
void addEdge(int u,int v,int w)
{
G[u].add(0,new Edge(v,w));
G[v].add(0,new Edge(u,w));
}
public int getWeight(int u, int v)
{
for (Edge e : G[u])
{
if (e.v == v)
{
return e.w ;
}
}throw new NoSuchElementException();
}
#Override
public String toString(){
String result="";
for(int i=0;i<G.length;i++)
result+=i+"=>"+G[i]+"\n";
return result;
}
// here's the problem though
void DFS(int s)
{
boolean visited[] = new boolean[G.length];
LinkedList<Integer> stack = new LinkedList<Integer>();
stack.push(s);
while (stack.size() != 0)
{
s = stack.pop();
System.out.print(s+" ");
Iterator<Edge> i = G[s].listIterator();
if (!visited[s])
{
visited[s] = true;
while (i.hasNext())
{
int n = i.next().v;
stack.push(n);
}
}
}
}
}
public class GraphEx
{
public static void main(String[] args)
{
Graph g=new Graph(10);
g.addEdge(1,2,38);
g.addEdge(1,5 ,19);
g.addEdge(1,3 ,35);
g.addEdge(1,4 ,11);
g.addEdge(4,3,27);
g.addEdge(3,6,13);
g.addEdge(3,5,28);
g.addEdge(5,6,26);
System.out.println(g);
System.out.println("\nDFS");
g.DFS(1);
This prints out:
DFS
1 2 1 5 1 3 1 4 1 3 6 3 5 5 6 3 4
That would be perfect if the first part didn't have the ones inserted for all the print numbers after 2 and then ended after 6. This is the closest output to what I think I should be getting I've gotten out of all the code I've written so I posted this.
EDIT: Here's the original that I'm trying to reconvert
void BFS(int s)
{
// Mark all the vertices as not visited(By default
// set as false)
boolean visited[] = new boolean[G.length];
// Create a queue for BFS
LinkedList<Integer> queue = new LinkedList<Integer>();
// Mark the current node as visited and enqueue it
visited[s]=true;
queue.add(s);
while (queue.size() != 0)
{
// Dequeue a vertex from queue and print it
s = queue.poll();
System.out.print(s+" ");
// Get all adjacent vertices of the dequeued vertex s
// If a adjacent has not been visited, then mark it
// visited and enqueue it
Iterator<Edge> i = G[s].listIterator();
while (i.hasNext())
{
int n = i.next().v;
if (!visited[n])
{
visited[n] = true;
queue.add(n);
}
}
}
}
DFS is an algorithm that is usually run on trees which do not have cycles or links back to their parents. This causes two pretty simple problems for your graph implementation. Problem 1 is that each vertex you have points back to it's "parent". For example, vertex 1 has an edge to vertex 2, and vertex 2 has an edge to vertex 1. When edge 2 is visited, all of it's children are put onto the stack. When this happens, you are putting vertex 1, which has been visited already, back onto the stack. Issue 2 is that sometimes you have vertices pushed onto the stack multiple times before they're visited. For example, vertices 5 and 3 both add 6 to the stack before 6 is visited. One way to quickly fix both of these problems is to do this:
while (stack.size() != 0)
{
s = stack.pop();
if(visited[s]) //add these two lines
continue;
System.out.print(s+" ");
Iterator<Edge> i = G[s].listIterator();
if (!visited[s])
{
visited[s] = true;
while (i.hasNext())
{
int n = i.next().v;
stack.push(n);
}
}
}
If you check the element popped off of the stack to see if it has been visited, you will remove both vertices which are parents that have already been visited, and nodes that have been pushed onto the stack multiple times by their parents. Simply check to see if a vertex has been visited, and if it has just continue with the next iteration of the loop.

Adjacency Linked List Cycle Detection - Java

I have some problem checking if my adjacency list has a cycle or not.
I want to make a function that checks if my adjacency list has existing at least one cycle.
Based on my program. First, I have to input the Root Node, followed by a number of nodes, the nodes in the graph, number of edges, and the adjacency list representing the edges. Each entry in the adjacency list contains a pair of nodes.
Sample input:
Root node: "A"
Number of nodes: 3
Vertices/Nodes:
A
B
C
Number of edges: 3
A
B
B
C
C
A
A --> B
B --> C
C --> A
The sample input above has a cycle: [ A --> B --> C --> A ] I want to output whether it has a cycle or not.
This is my program so far:
import java.util.Scanner;
class Neighbor {
public int vertexNum;
public Neighbor next;
public Neighbor(int vnum, Neighbor nbr) {
this.vertexNum = vnum;
next = nbr;
}
}
class Vertex {
String name;
Neighbor adjList;
Vertex(String name, Neighbor neighbors) {
this.name = name;
this.adjList = neighbors;
}
}
public class DirectedCycle {
Vertex[] adjLists;
public DirectedCycle() {
Scanner sc = new Scanner(System.in);
//Root Node
System.out.print("Root node: ");
String rn = sc.nextLine();
//Number of nodes
System.out.print("Number of vertices/nodes: ");
int nodes = sc.nextInt();
adjLists = new Vertex[nodes];
//List of nodes
System.out.println("Vertices:");
for (int v=0; v < adjLists.length; v++) {
String letter = sc.next();
adjLists[v] = new Vertex(letter, null);
}
//Number of edges
System.out.print("Number of edges: ");
int edges = sc.nextInt();
System.out.println("<v1> <v2>");
for(int i=0; i<edges; i++) {
int v1 = indexForName(sc.next());
int v2 = indexForName(sc.next());
adjLists[v1].adjList = new Neighbor(v2, adjLists[v1].adjList);
}
}
int indexForName(String name) {
for (int v=0; v < adjLists.length; v++) {
if (adjLists[v].name.equals(name)) {
return v;
}
}
return -1;
}
public void print() {
System.out.println();
for (int v=0; v < adjLists.length; v++) {
System.out.print(adjLists[v].name);
for (Neighbor nbr=adjLists[v].adjList; nbr != null; nbr=nbr.next) {
String name = adjLists[nbr.vertexNum].name;
System.out.print(" --> " + name);
}
System.out.println("\n");
}
}
public static void main(String[] args) {
DirectedCycle graph = new DirectedCycle();
graph.print();
}
}
My program above doesn't have yet a function that checks cycle and also I want to implement the root node thing.. If anyone can improve my program above just answer me and give me some code I can rely. Thanks! (I'm beginner!)
The most efficient way to detect a cycle in Floyd's Cycle detection algo., which is basically moving two pointers over the linked list, one moving at normal one step at a time slow pointer and the other with double the speed of the slow pointer, i.e fast pointer.
Java code for the same.
boolean detectloop(Node list) {
if(list == null)
return false;
Node slow, fast;
slow = fast = list;
while(true) {
slow = slow.next;
if(fast.next != null)
fast = fast.next.next;
else
return false;
if(slow == null || fast == null)
return false;
if(slow == fast)
return true;
}
}
To check a cycle of a linked list, you want to iterate though with two different pointers, one moving through the list twice as fast. If there is a cycle, it will eventually be detected using this method. Also, for the end condition, you can check to see if all nodes have been visited, and if so, there is no cycle.

Java: Adding nodes to graph bug

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.

Categories