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.
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;
}
I would appreciate any help...
I have 2 maze search algorithms which are DFS and BFS. The starting point is set at 0 and end point is set at 1. The nodes are placed in a stack and starts visiting its neighbors to find the path to 1. The nodes that are not involved in the path to 1 should be erased which is not happening. And also when the path finds the goal which is 1 it is not stopping.
Basically the testMaze path should be 0 5 4 1 whereas BFS is giving me 0 3 5 0 2 11 4 7 1 6 8 9 10 and
DFS is giving me 0, it initiates and it never finds anything. I think the problem might lie in either the printNode function or the visited, isVisited.
Below are the methods related to these problems. Thanks for any help in advance.
import java.util.*;
public class Maze {
public Node startingNode;
public ArrayList<Node> nodes = new ArrayList<>();
public int[][] matrix = new int[100][100];
// to set starting node at 0
public void setStartingNode(Node n) {
this.startingNode = n;
}
public Node getStartingNode() {
return this.startingNode;
}
public void addNode(int n) {
nodes.add(new Node (n));
}
public void visited(int n1) {
for(Node n2 : nodes) {
if(n2.list == n1) {
n2.visited = true;
}
}
}
public boolean isVisited(int n1) {
for(Node n2 : nodes) {
if(n2.list == n1) {
return n2.visited ;
}
}
return false;
}
public Node getNode(int n) {
for(Node n2 : nodes) {
if(n2.list == n) {
return n2;
}
}
return new Node(-1);
}
//TODO get the next unvisited node
public Node getNextNode(Node n) {
int link = n.list;
int i = 0;
while (i<nodes.size()) {
if(matrix[link][i] == 1 && isVisited(i) == false)
{
return (Node)getNode(i);
}
i++;
}
return null;
}
//algorithm uses queue and should find all paths
public void bfs() {
Queue<Node> q=new LinkedList<Node>();
q.add(this.startingNode);
printNode(this.startingNode);
startingNode.visited=true;
while(!q.isEmpty())
{
Node n=(Node)q.remove();//
Node child=null;//
while((child=getNextNode(n))!=null)
{
child.visited=true;
printNode(child);
q.add(child);
}
}
//Clear visited property of nodes
clearNodes();
}
// algorithm uses stack and should find fastest solution
public void dfs() {
Stack<Node> s=new Stack<Node>();
s.push(this.startingNode);
startingNode.visited=true;
printNode(startingNode);
while(!s.isEmpty())
{
Node n=(Node)s.peek();
Node child=getNextNode(n);
if(child!=null)
{
child.visited=true;
printNode(child);
s.push(child);
}
else
{
s.pop();
}
}
//Clear visited property of nodes
clearNodes();
}
private void clearNodes() {
int j = 0;
while (j < 0) {
Node n = (Node)nodes.get(j);
n.visited = false;
j++;
}
}
// to print nodes
private void printNode(Node n) {
System.out.print(n.list + " ");
}
}
Below is the main class
import java.util.*;
import java.io.*;
import javax.swing.*;
// C:\Users\Mannie\Desktop\maze1.txt
// C:\Users\Mannie\Desktop\maze2.txt
// C:\Users\Mannie\Desktop\maze3.txt
public class Main {
public static void main(String args[]) throws IOException {
String stringNode;
File file = new File(JOptionPane.showInputDialog("Please enter file path"));
ArrayList<String> nodes = new ArrayList<>();
Maze maze = new Maze();
maze.setStartingNode(new Node(0));
// idea is to convert string into 2D arrays here removing substring " " using .split
try {
try (Scanner sc = new Scanner(new FileInputStream(file))) {
while (sc.hasNextLine()) {
stringNode = sc.nextLine();
nodes.add(stringNode);
String[] segment = stringNode.split(" ");
//for (String val: ){
//the first time this loops the value will be 11, the second time it will be 3
//i have no idea what you
int intNode1 = Integer.parseInt(segment[0]);
int intNode2 = Integer.parseInt(segment[1]);
//System.out.println(intNode);
maze.matrix[intNode1][intNode2] = 1;
maze.matrix[intNode2][intNode1] = 1;
}
// nodes
for (int k=0;k<100;++k)
maze.nodes.add(new Node(k));
}
finally
{
}
} catch (FileNotFoundException e) {
}
Iterator<String> i = nodes.iterator();
while (i.hasNext()) {
System.out.println(i.next());
}
// To print bfs results
// also print the system clock time to time the algorithm using
// System.nanoTime();
maze.bfs();
System.nanoTime();
System.out.println();
// To print dfs results
// also print the system clock time to time the algorithm using
// System.nanoTime();
maze.dfs();
System.nanoTime();
}
}
Here is the Node class which just passes through the nodes
public class Node {
public int list;
public boolean visited = false;
public Node(int node) {
this.list = node;
}
}
In your code
public Node getNode(int n) {
for(Node n2 : nodes) {
if(n2.list == n) {
return n2;
}
}
return new Node(-1);
}
you are returning a new Node(-1); instead of null as you expect here:
while((child=getNextNode(n))!=null)
{
child.visited=true;
printNode(child);
q.add(child);
}
This causes wrong nodes to be printed and it will not stop. This code was takes from bfs() but also applies to dfs(). You should return null instead.
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.
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).
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.