Skip to content

Commit 609e155

Browse files
TripleCamellyaczgdp1807
authored andcommitted
feat: Add Tarjan's strongly connected components algorithm
1 parent 513ba92 commit 609e155

File tree

2 files changed

+51
-1
lines changed

2 files changed

+51
-1
lines changed

pydatastructs/graphs/algorithms.py

+48
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,52 @@ def _strongly_connected_components_kosaraju_adjacency_list(graph):
531531
_strongly_connected_components_kosaraju_adjacency_matrix = \
532532
_strongly_connected_components_kosaraju_adjacency_list
533533

534+
def _tarjan_dfs(u, graph, index, stack, indices, low_links, on_stacks, components):
535+
indices[u] = index[0]
536+
low_links[u] = index[0]
537+
index[0] += 1
538+
stack.append(u)
539+
on_stacks[u] = True
540+
541+
for node in graph.neighbors(u):
542+
v = node.name
543+
if indices[v] == -1:
544+
_tarjan_dfs(v, graph, index, stack, indices, low_links, on_stacks, components)
545+
low_links[u] = min(low_links[u], low_links[v])
546+
elif on_stacks[v]:
547+
low_links[u] = min(low_links[u], low_links[v])
548+
549+
if low_links[u] == indices[u]:
550+
component = set()
551+
while stack:
552+
w = stack.pop()
553+
on_stacks[w] = False
554+
component.add(w)
555+
if w == u:
556+
break
557+
components.append(component)
558+
559+
def _strongly_connected_components_tarjan_adjacency_list(graph):
560+
index = [0] # mutable object
561+
stack = Stack([])
562+
indices, low_links, on_stacks = {}, {}, {}
563+
564+
for u in graph.vertices:
565+
indices[u] = -1
566+
low_links[u] = -1
567+
on_stacks[u] = False
568+
569+
components = []
570+
571+
for u in graph.vertices:
572+
if indices[u] == -1:
573+
_tarjan_dfs(u, graph, index, stack, indices, low_links, on_stacks, components)
574+
575+
return components
576+
577+
_strongly_connected_components_tarjan_adjacency_matrix = \
578+
_strongly_connected_components_tarjan_adjacency_list
579+
534580
def strongly_connected_components(graph, algorithm, **kwargs):
535581
"""
536582
Computes strongly connected components for the given
@@ -549,6 +595,7 @@ def strongly_connected_components(graph, algorithm, **kwargs):
549595
supported,
550596
551597
'kosaraju' -> Kosaraju's algorithm as given in [1].
598+
'tarjan' -> Tarjan's algorithm as given in [2].
552599
backend: pydatastructs.Backend
553600
The backend to be used.
554601
Optional, by default, the best available
@@ -578,6 +625,7 @@ def strongly_connected_components(graph, algorithm, **kwargs):
578625
==========
579626
580627
.. [1] https://en.wikipedia.org/wiki/Kosaraju%27s_algorithm
628+
.. [2] https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm
581629
582630
"""
583631
raise_if_backend_is_not_python(

pydatastructs/graphs/tests/test_algorithms.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -188,11 +188,13 @@ def _test_strongly_connected_components(func, ds, algorithm, *args):
188188
graph.add_edge(h.name, g.name)
189189
comps = func(graph, algorithm)
190190
expected_comps = [{'e', 'a', 'b'}, {'d', 'c', 'h'}, {'g', 'f'}]
191-
assert comps == expected_comps
191+
assert comps.sort() == expected_comps.sort()
192192

193193
scc = strongly_connected_components
194194
_test_strongly_connected_components(scc, "List", "kosaraju")
195195
_test_strongly_connected_components(scc, "Matrix", "kosaraju")
196+
_test_strongly_connected_components(scc, "List", "tarjan")
197+
_test_strongly_connected_components(scc, "Matrix", "tarjan")
196198

197199
def test_depth_first_search():
198200

0 commit comments

Comments
 (0)