@@ -10,10 +10,23 @@ class DirectedGraph:
1010 def __init__ (self ) -> None :
1111 self .graph = {}
1212
13- # adding vertices and edges
14- # adding the weight is optional
15- # handles repetition
1613 def add_pair (self , u , v , w = 1 ) -> None :
14+ """
15+ Adds a directed edge u->v with weight w.
16+ Add vertices and edges
17+ Add the weight is optional
18+ Handle repetition
19+
20+ >>> dg = DirectedGraph()
21+ >>> dg.add_pair(-1,2)
22+ >>> dg.add_pair(1,3,5)
23+ >>> dg.add_pair(1,3,5)
24+ >>> dg.add_pair(1,3,6)
25+ >>> dg.all_nodes()
26+ [-1, 2, 1, 3]
27+ >>> dg.graph[1]
28+ [[5, 3], [6, 3]]
29+ """
1730 if self .graph .get (u ):
1831 if self .graph [u ].count ([w , v ]) == 0 :
1932 self .graph [u ].append ([w , v ])
@@ -23,53 +36,94 @@ def add_pair(self, u, v, w=1) -> None:
2336 self .graph [v ] = []
2437
2538 def all_nodes (self ):
39+ """
40+ Returns list of all nodes in the graph.
41+ >>> dg = DirectedGraph()
42+ >>> dg.all_nodes()
43+ []
44+ >>> dg.add_pair(1,1)
45+ >>> dg.all_nodes()
46+ [1]
47+ >>> dg.add_pair(2,3,3)
48+ >>> dg.all_nodes()
49+ [1, 2, 3]
50+ """
2651 return list (self .graph )
2752
2853 # handles if the input does not exist
2954 def remove_pair (self , u , v ) -> None :
55+ """
56+ Removes all edges u->v if it exists.
57+ >>> dg = DirectedGraph()
58+ >>> dg.remove_pair(1,2) # silently exits
59+ >>> dg.add_pair(0,5,2)
60+ >>> dg.graph[0]
61+ [[2, 5]]
62+ >>> dg.remove_pair(5,0)
63+ >>> dg.graph[0]
64+ [[2, 5]]
65+ >>> dg.remove_pair(0,5)
66+ >>> dg.graph[0]
67+ []
68+ """
3069 if self .graph .get (u ):
3170 for _ in self .graph [u ]:
3271 if _ [1 ] == v :
3372 self .graph [u ].remove (_ )
3473
3574 # if no destination is meant the default value is -1
3675 def dfs (self , s = - 2 , d = - 1 ):
37- if s == d :
38- return []
76+ """
77+ Performs depth first search from s to find d.
78+ Returns the path s->d as a list.
79+ Returns dfs from s if d is not found
80+ >>> dg = DirectedGraph()
81+ >>> dg.dfs()
82+ []
83+ >>> dg.add_pair(1,1)
84+ >>> dg.dfs(1,1)
85+ [1]
86+ >>> dg = DirectedGraph()
87+ >>> dg.add_pair(0,1)
88+ >>> dg.add_pair(0,2)
89+ >>> dg.add_pair(1,3)
90+ >>> dg.add_pair(1,4)
91+ >>> dg.add_pair(1,5)
92+ >>> dg.add_pair(2,5)
93+ >>> dg.add_pair(5,6)
94+ >>> dg.dfs(0,6)
95+ [0, 2, 5, 6]
96+ >>> dg.dfs(1,6)
97+ [1, 5, 6]
98+ >>> dg.dfs()
99+ [0, 2, 5, 6, 1, 4, 3]
100+ >>> dg.dfs(1,0)
101+ [1, 5, 6, 4, 3]
102+ """
39103 stack = []
40104 visited = []
41105 if s == - 2 :
42- s = next (iter (self .graph ))
43- stack .append (s )
44- visited .append (s )
45- ss = s
46-
47- while True :
48- # check if there is any non isolated nodes
49- if len (self .graph [s ]) != 0 :
50- ss = s
51- for node in self .graph [s ]:
52- if visited .count (node [1 ]) < 1 :
53- if node [1 ] == d :
54- visited .append (d )
55- return visited
56- else :
57- stack .append (node [1 ])
58- visited .append (node [1 ])
59- ss = node [1 ]
60- break
61-
62- # check if all the children are visited
63- if s == ss :
64- stack .pop ()
65- if len (stack ) != 0 :
66- s = stack [len (stack ) - 1 ]
106+ if self .graph .get (s , None ):
107+ pass # -2 is a node
108+ elif len (self .graph ) > 0 :
109+ s = next (iter (self .graph ))
67110 else :
68- s = ss
111+ return [] # Graph empty
112+ stack .append (s )
69113
70- # check if se have reached the starting point
71- if len (stack ) == 0 :
72- return visited
114+ # Run dfs
115+ while len (stack ) > 0 :
116+ s = stack .pop ()
117+ visited .append (s )
118+ # If reached d, return
119+ if s == d :
120+ break
121+
122+ # add not visited child nodes to stack
123+ for _ , ss in self .graph [s ]:
124+ if visited .count (ss ) < 1 :
125+ stack .append (ss )
126+ return visited
73127
74128 # c is the count of nodes you want and if you leave it or pass -1 to the function
75129 # the count will be random from 10 to 10000
@@ -84,12 +138,42 @@ def fill_graph_randomly(self, c=-1) -> None:
84138 self .add_pair (i , n , 1 )
85139
86140 def bfs (self , s = - 2 ):
141+ """
142+ Performs breadth first search from s
143+ Returns list.
144+ >>> dg = DirectedGraph()
145+ >>> dg.bfs()
146+ []
147+ >>> dg.add_pair(1,1)
148+ >>> dg.bfs(1)
149+ [1]
150+ >>> dg = DirectedGraph()
151+ >>> dg.add_pair(0,1)
152+ >>> dg.add_pair(0,2)
153+ >>> dg.add_pair(1,3)
154+ >>> dg.add_pair(1,4)
155+ >>> dg.add_pair(1,5)
156+ >>> dg.add_pair(2,5)
157+ >>> dg.add_pair(5,6)
158+ >>> dg.bfs(0)
159+ [0, 1, 2, 3, 4, 5, 6]
160+ >>> dg.bfs(1)
161+ [1, 3, 4, 5, 6]
162+ >>> dg.bfs()
163+ [0, 1, 2, 3, 4, 5, 6]
164+ """
87165 d = deque ()
88166 visited = []
89167 if s == - 2 :
90- s = next (iter (self .graph ))
168+ if self .graph .get (s , None ):
169+ pass # -2 is a node
170+ elif len (self .graph ) > 0 :
171+ s = next (iter (self .graph ))
172+ else :
173+ return [] # Graph empty
91174 d .append (s )
92175 visited .append (s )
176+ # Run bfs
93177 while d :
94178 s = d .popleft ()
95179 if len (self .graph [s ]) != 0 :
@@ -298,42 +382,59 @@ def remove_pair(self, u, v) -> None:
298382
299383 # if no destination is meant the default value is -1
300384 def dfs (self , s = - 2 , d = - 1 ):
301- if s == d :
302- return []
385+ """
386+ Performs depth first search from s to find d.
387+ Returns the path s->d as a list.
388+ Returns dfs from s if d is not found
389+ >>> ug = Graph()
390+ >>> ug.dfs()
391+ []
392+ >>> ug.add_pair(1,1)
393+ >>> ug.dfs(1,1)
394+ [1]
395+ >>> ug = Graph()
396+ >>> ug.add_pair(0,1)
397+ >>> ug.add_pair(0,2)
398+ >>> ug.add_pair(1,3)
399+ >>> ug.add_pair(1,4)
400+ >>> ug.add_pair(1,5)
401+ >>> ug.add_pair(2,5)
402+ >>> ug.add_pair(5,6)
403+ >>> ug.dfs(0,6)
404+ [0, 2, 5, 6]
405+ >>> ug.dfs(1,6)
406+ [1, 5, 6]
407+ >>> ug.dfs()
408+ [0, 2, 5, 6, 1, 4, 3]
409+ >>> ug.dfs(1,0)
410+ [1, 5, 6, 2, 0]
411+ """
303412 stack = []
304413 visited = []
305414 if s == - 2 :
306- s = next (iter (self .graph ))
307- stack .append (s )
308- visited .append (s )
309- ss = s
310-
311- while True :
312- # check if there is any non isolated nodes
313- if len (self .graph [s ]) != 0 :
314- ss = s
315- for node in self .graph [s ]:
316- if visited .count (node [1 ]) < 1 :
317- if node [1 ] == d :
318- visited .append (d )
319- return visited
320- else :
321- stack .append (node [1 ])
322- visited .append (node [1 ])
323- ss = node [1 ]
324- break
325-
326- # check if all the children are visited
327- if s == ss :
328- stack .pop ()
329- if len (stack ) != 0 :
330- s = stack [len (stack ) - 1 ]
415+ if self .graph .get (s , None ):
416+ pass # -2 is a node
417+ elif len (self .graph ) > 0 :
418+ s = next (iter (self .graph ))
331419 else :
332- s = ss
420+ return [] # Graph empty
421+ stack .append (s )
333422
334- # check if se have reached the starting point
335- if len (stack ) == 0 :
336- return visited
423+ # Run dfs
424+ while len (stack ) > 0 :
425+ s = stack .pop ()
426+ if visited .count (s ) == 1 :
427+ continue
428+ visited .append (s )
429+ # If reached d, return
430+ if s == d :
431+ break
432+
433+ # add not visited child nodes to stack
434+ for _ , ss in self .graph [s ]:
435+ if visited .count (ss ) < 1 :
436+ stack .append (ss )
437+ return visited
337438
338439 # c is the count of nodes you want and if you leave it or pass -1 to the function
339440 # the count will be random from 10 to 10000
@@ -348,10 +449,39 @@ def fill_graph_randomly(self, c=-1) -> None:
348449 self .add_pair (i , n , 1 )
349450
350451 def bfs (self , s = - 2 ):
452+ """
453+ Performs breadth first search from s
454+ Returns list.
455+ >>> ug = Graph()
456+ >>> ug.bfs()
457+ []
458+ >>> ug.add_pair(1,1)
459+ >>> ug.bfs(1)
460+ [1]
461+ >>> ug = Graph()
462+ >>> ug.add_pair(0,1)
463+ >>> ug.add_pair(0,2)
464+ >>> ug.add_pair(1,3)
465+ >>> ug.add_pair(1,4)
466+ >>> ug.add_pair(1,5)
467+ >>> ug.add_pair(2,5)
468+ >>> ug.add_pair(5,6)
469+ >>> ug.bfs(0)
470+ [0, 1, 2, 3, 4, 5, 6]
471+ >>> ug.bfs(1)
472+ [1, 0, 3, 4, 5, 2, 6]
473+ >>> ug.bfs()
474+ [0, 1, 2, 3, 4, 5, 6]
475+ """
351476 d = deque ()
352477 visited = []
353478 if s == - 2 :
354- s = next (iter (self .graph ))
479+ if self .graph .get (s , None ):
480+ pass # -2 is a node
481+ elif len (self .graph ) > 0 :
482+ s = next (iter (self .graph ))
483+ else :
484+ return [] # Graph empty
355485 d .append (s )
356486 visited .append (s )
357487 while d :
0 commit comments