How to do DFS and BFS in Adjacency List? - java

Creating a Adjacency List
HashMap <Interger,ArrayList<Integer>> adjList = new HashMap<Integer,ArrayList<Integer>>();
// adding element in Adjacency list (Undirected)
void AdjList(Integer a, Integer b){
adjList.putIfAbsent(a, new ArrayList<>());
adjList.get(a).add(b);
adjList.putIfAbsent(b, new ArrayList<>());
adjList.get(b).add(a);
}
How to do DFS and BFS in this?
I've tried something like this. how to loop through ?
void DFS(Integer i) {
//gettting first element from adjlist
if (adjList.containsKey(i)) {
Integer ele1 = adjList.get(i).get(adjList.get(i).size() - 1);
if (adjList.containsKey(ele1)) {
Integer ele2 = adjList.get(ele1).get(adjList.get(ele1).size() - 1);
}
}
}

You are creating Adjacency List correctly(but it is better to name this function something like adjList), but for both BFS and DFS, you need to have a visited status per node, and iterate over all nodes neighbors of a node and do the BFS/DFS recursively on them.
import java.util.*;
public class Graph {
public static void main(String[] args) {
Graph g = new Graph();
g.adjList(0, 1);
g.adjList(0, 2);
g.adjList(1, 3);
g.adjList(2, 3);
g.DFS(0);
g.BFS(0);
}
HashMap<Integer, ArrayList<Integer>> adjList = new HashMap<>();
// adding element in Adjacency list (Undirected)
void adjList(Integer a, Integer b) {
adjList.putIfAbsent(a, new ArrayList<>());
adjList.get(a).add(b);
adjList.putIfAbsent(b, new ArrayList<>());
adjList.get(b).add(a);
}
void dfsRecursive(int v, boolean[] visited) {
visited[v] = true;
System.out.print(v + " ");
for (int n : adjList.get(v)) {
if (!visited[n])
dfsRecursive(n, visited);
}
}
void DFS(int s) {
boolean[] visited = new boolean[adjList.size()];
System.out.print("DFS: ");
dfsRecursive(s, visited);
System.out.println();
}
void BFS(int s) {
boolean[] visited = new boolean[adjList.size()];
LinkedList<Integer> queue = new LinkedList<>();
visited[s] = true;
queue.add(s);
System.out.print("BFS: ");
while (queue.size() != 0) {
s = queue.poll();
System.out.print(s + " ");
for (int n : adjList.get(s)) {
if (!visited[n]) {
visited[n] = true;
queue.add(n);
}
}
}
}
}
The output of above code would be:
DFS: 0 1 3 2
BFS: 0 1 2 3

Related

Represent a graph containing directed and undirected edges using List<Integer>

I was asked this question in one of my google interviews. I couldn't figure it out. If someone can help that would be great :)
The class provided was
class Node{
int data,
List<Node> outEdges;
}
if you're provided a Node stream containing both directed and undirected edges you have to encode it in such a way that it return List and and decode again to original graph
List<Integer> encode(Node root){
}
Node decode(List<Integer> graph){
}
The hint provided was you can add your own integers if you want
You could just put the data and all the edges in the list and using null as delimiter:
private class IndexAndEdge {
public Set<Integer> edges = new HashSet<>();
public int index;
public int data;
}
List<Integer> encode(Node root) {
List<Integer> result = new ArrayList<>();
Map<Node, IndexAndEdge> lookup = new HashMap<>();
parse(root, lookup);
result.add(lookup.size());
lookup.values().stream()
.sorted((a, b) -> Integer.compare(a.index, b.index))
.forEach(iae -> {
result.add(iae.data);
result.addAll(iae.edges);
result.add(null);
});
result.remove(result.size() - 1);
return result;
}
private int parse(Node node, Map<Node, IndexAndEdge> lookup) {
if (lookup.containsKey(node))
return lookup.get(node).index;
IndexAndEdge iae = new IndexAndEdge();
iae.index = lookup.size();
iae.data = node.data;
lookup.put(node, iae);
for (Node n : node.outEdges)
iae.edges.add(parse(n, lookup));
return iae.index;
}
Node decode(List<Integer> graph) {
Node[] nodes = new Node[graph.get(0)];
for (int i = 0; i < nodes.length; i++) {
nodes[i] = new Node();
nodes[i].outEdges = new ArrayList<>();
}
int index = 0;
for (int i = 1; i < graph.size(); i++) {
Integer n = graph.get(i);
if (n == null)
index++;
else if (nodes[index].outEdges.isEmpty())
nodes[index].data = n;
else
nodes[index].outEdges.add(nodes[n]);
}
return nodes[0];
}

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

LinkedList for each index in the LinkedList Array

What is the problem here?.I'm trying to implement the graph data structure,using the adjacency lists,by utilising the Collections from the util package.Here
LinkedList array which holds some integer.
Each element of that LinkedList holds another LinkedList of type: node.
But during the compilation process, it says incompatible types.
How to resolve this problem?
//Sum of dependencies in a graph
import java.util.*;
class node
{
int vertex,weight;
public node(int v,int w)
{
vertex = v;
weight = w;
}
}
public class dependency
{
int V;
LinkedList<Integer> adj[];
public dependency(int v)
{
V = v;
adj = new LinkedList<Integer>[v];
for (int i=0;i < v ;i++ ) {
adj[i] = new LinkedList<node>();
}
}
void addEdge(int v,node l)
{
adj[v].add(l);
}
void BFS(int s)
{
boolean visited[] = new boolean[V];
LinkedList<Integer> queue = new LinkedList<Integer>();
visited[s] = true;
queue.add(s);
while(queue.size() != 0)
{
s = queue.poll();
System.out.println(s+" ");
Iterator<Integer> i = adj[s].listIterator();
while(i.hasNext())
{
int n = i.next();
if(!visited[n])
{
visited[n] = true;
queue.add(n);
}
}
}
}
public static void main(String[] args) {
graph g = new graph(4);
node a = new node(1,10);
node b = new node(2,20);
node c = new node(2,30);
node d = new node(0,20);
node e = new node(3,30);
node f = new node(3,20);
g.addEdge(0, a);
g.addEdge(0, b);
g.addEdge(1, c);
g.addEdge(2, d);
g.addEdge(2, e);
g.addEdge(3, f);
System.out.println("Following is Breadth First Traversal "+
"(starting from vertex 2)");
g.BFS(2);
}
}
You've declared an array of LinkedLists of type LinkedList<Integer>, but you're trying to store LinkedList<node> in the array. It doesn't appear that you're ever using the weight attribute of node, so you should change adj[i] = new LinkedList<node>(); to adj[i] = new LinkedList<Integer>();.

I hava a maze search algorithm and is not stopping at end point an is also printing unwanted nodes

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.

DFS java pathfinding problems

I'm developing a search algorithm for finding paths in a graph. In this algorithm i need to find all the paths in an undirected, not weighted graph that go trough each graph connection only once.
Currently, what my prgoram is doing, is finding all the paths that go trough each node only once. I need connections and not nodes.
Here is my code:
import java.util.*;
public class dfs {
private static Map<Integer, LinkedHashSet<Integer>> map = new HashMap<Integer, LinkedHashSet<Integer>>();
private int startNode;
private int numLinks;
public dfs(int startNode, int numLinks) {
super();
this.startNode = startNode;
this.numLinks = numLinks;
}
public int getNumLinks(){
return numLinks;
}
public void addEdge(int source, int destiny) {
LinkedHashSet<Integer> adjacente = map.get(source);
if(adjacente==null) {
adjacente = new LinkedHashSet<Integer>();
map.put(source, adjacente);
}
adjacente.add(destiny);
}
public void addLink(int source, int destiny) {
addEdge(source, destiny);
addEdge(destiny, source);
}
public LinkedList<Integer> adjacentNodes(int adj) {
LinkedHashSet<Integer> adjacente = map.get(adj);
System.out.println("adjacentes:" + adjacente);
if(adjacente==null) {
return new LinkedList<Integer>();
}
return new LinkedList<Integer>(adjacente);
}
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int numVertices = input.nextInt();
int numLinks = input.nextInt();
int startNode = input.nextInt();
int endNode = startNode;
dfs mapa = new dfs(startNode, numLinks);
for(int i = 0; i<numLinks; i++){
mapa.addLink(input.nextInt(), input.nextInt());
}
List<ArrayList<Integer>> paths = new ArrayList<ArrayList<Integer>>();
List<Integer> visited = new ArrayList<Integer>();
visited.add(startNode);
Integer currentNode = 0;
Iterator it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pairs = (Map.Entry)it.next();
currentNode = (Integer) pairs.getKey();
mapa.findAllPaths(mapa, visited, paths, currentNode);
}
}
private void findAllPaths(dfs mapa, List<Integer> visited,
List<ArrayList<Integer>> paths, Integer currentNode) {
if (currentNode.equals(startNode)) {
paths.add(new ArrayList<Integer>(visited));
LinkedList<Integer> nodes = mapa.adjacentNodes(currentNode);
for (Integer node : nodes) {
List<Integer> temp = new ArrayList<Integer>();
temp.addAll(visited);
temp.add(node);
System.out.println("temp:" + temp);
findAllPaths(mapa, temp, paths, node);
}
}
else {
LinkedList<Integer> nodes = mapa.adjacentNodes(currentNode);
System.out.println("currentNode:" + currentNode);
List<Integer> inseridos = new ArrayList<Integer>();
for (Integer node : nodes) {
if (visited.contains(node)) {
continue;
}
List<Integer> temp = new ArrayList<Integer>();
inseridos.add(currentNode);
temp.addAll(visited);
System.out.println("visited:" + visited);
temp.add(node);
findAllPaths(mapa, temp, paths, node);
}
}
}
}
Right now, i think the following code:
if (visited.contains(node)) {
continue;
}
is making that the program not going through each node more than once.
I need helping transforming my program to go trough each connection only once, and not through each node only once.
(I'm sorry about my english, i'm not a native)
If you're willing to do some rewriting, I think this kind of problem is more cleanly expressed in an OO fashion.
You could build a linked graph out of Node and Edge instances, allowing you to mark visited edges as you traverse the graph.
class Node
{
List<Edge> adjacentEdges;
boolean isVisited;
}
class Edge
{
Node node1;
Node node2;
boolean isVisited;
}

Categories