11package com .rampatra .common ;
22
3+ import java .util .ArrayDeque ;
34import java .util .HashMap ;
45import java .util .HashSet ;
56import java .util .Iterator ;
67import java .util .Map ;
8+ import java .util .Queue ;
79import java .util .Set ;
10+ import java .util .stream .Collectors ;
811
912/**
1013 * @author rampatra
@@ -14,32 +17,47 @@ public class UndirectedGraph<E extends Comparable<E>> extends Graph<E> {
1417 // map for a fast lookup
1518 private Map <E , GraphNode <E >> nodes = new HashMap <>();
1619
20+ /**
21+ * Adds an edge between a node with value {@code value} and another node with value {@code adjacentValue}.
22+ * If nodes with respective values are not present in the graph then this method creates them.
23+ *
24+ * @param value refers to the value for first node
25+ * @param adjacentValue refers to the value for the second node
26+ * @return the node with value {@code value}, or the first node
27+ */
1728 public GraphNode <E > addEdge (E value , E adjacentValue ) {
1829 GraphNode <E > node = nodes .get (value );
1930 GraphNode <E > adjNode = nodes .get (adjacentValue );
20- if (node == null ) {
31+ if (node == null && value != null ) {
2132 node = new GraphNode <>(value );
2233 nodes .put (value , node );
2334 }
24- if (adjNode == null ) {
35+ if (adjNode == null && adjacentValue != null ) {
2536 adjNode = new GraphNode <>(adjacentValue );
2637 nodes .put (adjacentValue , adjNode );
2738 }
28- node .adjacentNodes .add (adjNode );
29- adjNode .adjacentNodes .add (node ); // as this is an undirected graph
39+ if (node != null && adjNode != null ) {
40+ node .adjacentNodes .add (adjNode );
41+ adjNode .adjacentNodes .add (node ); // as this is an undirected graph
42+ }
3043 return node ;
3144 }
3245
33- // todo
46+ /**
47+ * Method to check whether {@code src} and {@code dest} nodes are connected by depth first search (DFS).
48+ *
49+ * @param src source node in graph
50+ * @param dest destination node in graph
51+ * @return {@code true} if there is a path from {@code src} to {@code dest}, {@code false} otherwise
52+ */
3453 public boolean hasPathDFS (E src , E dest ) {
3554 GraphNode <E > s = nodes .get (src );
3655 GraphNode <E > d = nodes .get (dest );
37- Set <GraphNode <E >> visited = new HashSet <>();
56+ Set <GraphNode <E >> visited = new HashSet <>(); // to save all visited nodes so that we do not visit them again
3857 return hasPathDFS (s , d , visited );
3958 }
4059
41- // todo
42- public boolean hasPathDFS (GraphNode <E > src , GraphNode <E > dest , Set <GraphNode <E >> visited ) {
60+ private boolean hasPathDFS (GraphNode <E > src , GraphNode <E > dest , Set <GraphNode <E >> visited ) {
4361 if (src == null || dest == null ) {
4462 return false ;
4563 }
@@ -56,6 +74,45 @@ public boolean hasPathDFS(GraphNode<E> src, GraphNode<E> dest, Set<GraphNode<E>>
5674 return false ;
5775 }
5876
77+ /**
78+ * Method to check whether {@code src} and {@code dest} nodes are connected by breadth first search (BFS).
79+ *
80+ * @param src source node in graph
81+ * @param dest destination node in graph
82+ * @return {@code true} if there is a path from {@code src} to {@code dest}, {@code false} otherwise
83+ */
84+ public boolean hasPathBFS (E src , E dest ) {
85+ GraphNode <E > s = nodes .get (src );
86+ GraphNode <E > d = nodes .get (dest );
87+ if (s == null || d == null ) {
88+ return false ;
89+ }
90+ Set <GraphNode <E >> visited = new HashSet <>();
91+ Queue <GraphNode <E >> toVisit = new ArrayDeque <>();
92+ toVisit .add (s );
93+ return hasPathBFS (d , visited , toVisit );
94+ }
95+
96+ private boolean hasPathBFS (GraphNode <E > dest , Set <GraphNode <E >> visited , Queue <GraphNode <E >> toVisit ) {
97+ while (!toVisit .isEmpty ()) {
98+ GraphNode <E > node = toVisit .poll ();
99+ if (visited .contains (node )) {
100+ continue ;
101+ } else {
102+ visited .add (node );
103+ }
104+ toVisit .addAll (node .adjacentNodes .stream ().filter (n -> !visited .contains (n )).collect (Collectors .toList ()));
105+ if (node .value .compareTo (dest .value ) == 0 ) {
106+ return true ;
107+ }
108+ }
109+ return false ;
110+ }
111+
112+
113+ /**
114+ * Prints the node values in the graph.
115+ */
59116 public void print () {
60117 Set <E > visited = new HashSet <>();
61118 System .out .print ("[" );
@@ -82,12 +139,27 @@ public static void main(String[] args) {
82139 graph .addEdge (5 , 1 );
83140 graph .addEdge (5 , 6 );
84141 graph .addEdge (8 , null );
142+ graph .addEdge (null , 9 );
85143 graph .print ();
86- // todo
144+
145+ System .out .println ("----" );
146+
147+ // has path DFS
87148 System .out .println (graph .hasPathDFS (1 , 5 ));
88149 System .out .println (graph .hasPathDFS (1 , 6 ));
89150 System .out .println (graph .hasPathDFS (1 , 8 ));
90151 System .out .println (graph .hasPathDFS (4 , 8 ));
152+ System .out .println (graph .hasPathDFS (4 , 9 ));
91153 System .out .println (graph .hasPathDFS (4 , 100 ));
154+
155+ System .out .println ("----" );
156+
157+ // has path BFS
158+ System .out .println (graph .hasPathBFS (1 , 5 ));
159+ System .out .println (graph .hasPathBFS (1 , 6 ));
160+ System .out .println (graph .hasPathBFS (1 , 8 ));
161+ System .out .println (graph .hasPathBFS (4 , 8 ));
162+ System .out .println (graph .hasPathBFS (4 , 9 ));
163+ System .out .println (graph .hasPathBFS (4 , 100 ));
92164 }
93165}
0 commit comments