Skip to content

Commit 4b22b9e

Browse files
feat: Add Tarjan's strongly connected components algorithm
1 parent f34b7d6 commit 4b22b9e

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
@@ -530,6 +530,52 @@ def _strongly_connected_components_kosaraju_adjacency_list(graph):
530530
_strongly_connected_components_kosaraju_adjacency_matrix = \
531531
_strongly_connected_components_kosaraju_adjacency_list
532532

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