Kosaraju: Difference between revisions

22,301 bytes added ,  13 days ago
m
 
(31 intermediate revisions by 14 users not shown)
Line 4:
<br>
Kosaraju's algorithm (also known as the Kosaraju–Sharir algorithm) is a linear time algorithm to find the strongly connected components of a directed graph. Aho, Hopcroft and Ullman credit it to an unpublished paper from 1978 by S. Rao Kosaraju. The same algorithm was independently discovered by Micha Sharir and published by him in 1981. It makes use of the fact that the transpose graph (the same graph with the direction of every edge reversed) has exactly the same strongly connected components as the original graph.
<br>
For this task consider the directed graph with these connections:
0 -> 1
1 -> 2
2 -> 0
3 -> 1, 3 -> 2, 3 -> 4
4 -> 3, 4 -> 5
5 -> 2, 5 -> 6
6 -> 5
7 -> 4, 7 -> 6, 7 -> 7
 
And report the kosaraju strongly connected component for each node.
<br>
;References:
* The article on [[wp:Kosaraju's_algorithm|Wikipedia]].
 
=={{header|C11l}}==
{{trans|Python}}
<lang c>#include <stdio.h>
#include <stdlib.h>
 
<syntaxhighlight lang="11l">F kosaraju(g)
struct stack {
V size = g.len
int state;
V vis void= [0B] * *current;size
V l struct= stack[0] *next; size
V x = size
};
V t = [[Int]()] * size
 
F visit(Int u) -> Void
struct graph {
int I value;!@vis[u]
int @vis[u] = state;1B
struct stack *incoming; L(v) @g[u]
struct stack *outgoing; @visit(v)
@t[v] [+]= u
};
@x--
@l[@x] = u
 
L(u) 0 .< g.len
void create(struct stack **stack)
visit(u)
{
V *stackc = NULL;[0] * size
}
 
F assign(Int u, root) -> Void
void push(int state, void *value, struct stack **stack)
I @vis[u]
{
@vis[u] = 0B
struct stack *new = malloc(sizeof (struct stack));
new->state @c[u] = state;root
new->current = value; L(v) @t[u]
new->next = *stack; @assign(v, root)
*stack = new;
}
 
L(u) l
int pop(int *state, void **value, struct stack **stack)
assign(u, u)
{
R c
struct stack *old = *stack;
if (!old) return 0;
if (state) *state = old->state;
if (value) *value = old->current;
*stack = old->next;
free(old);
return 1;
}
 
V g = [[1], [2], [0], [1, 2, 4], [3, 5], [2, 6], [5], [4, 6, 7]]
void destroy(struct stack **stack)
print(kosaraju(g))</syntaxhighlight>
{
while (pop(NULL, NULL, stack));
}
 
{{out}}
void connect(struct graph *source, struct graph *target)
<pre>
{
[0, 0, 0, 3, 3, 5, 5, 7]
push(0, target, &source->outgoing);
</pre>
push(0, source, &target->incoming);
}
 
=={{header|C sharp|C#}}==
void path(int count, int *offsets, struct graph *nodes)
<syntaxhighlight lang="csharp">using System;
{
using System.Collections.Generic;
while (count--)
connect(&nodes[offsets[count]], &nodes[offsets[count + 1]]);
}
 
class Node
void visit(struct graph *graph, struct stack **visited)
{
public enum Colors
int state;
{
void *current;
Black, White, Gray
struct stack *schedule;
}
struct stack *neighbors;
struct stack dummy = { 0, graph, NULL };
create(&schedule);
push(0, &dummy, &schedule);
while (pop(&state, &current, &schedule))
if (!state && current) {
neighbors = current;
graph = neighbors->current;
push(0, neighbors->next, &schedule);
if (!graph->state) {
graph->state = 1;
push(1, graph, &schedule);
push(0, graph->outgoing, &schedule);
}
}
else if (state)
push(0, current, visited);
}
 
public Colors color { get; set; }
void assign(struct graph *graph, struct stack **assigned)
public int N { get; }
{
struct stack *schedule;
public Node(int n)
struct stack *neighbors;
{
struct stack dummy = { 0, graph, NULL };
N = n;
color = Colors.White;
create(&schedule);
}
push(0, &dummy, &schedule);
while (pop(NULL, &neighbors, &schedule))
if (neighbors) {
graph = neighbors->current;
push(0, neighbors->next, &schedule);
if (graph->state) {
graph->state = 0;
push(0, graph->incoming, &schedule);
push(0, graph, assigned);
}
}
}
 
class Graph
void kosaraju(struct graph *graph, struct stack **components)
{
public HashSet<Node> V { get; }
struct stack *visited;
public Dictionary<Node, HashSet<Node>> Adj { get; }
struct stack *assigned;
 
/// <summary>
create(&visited);
/// Kosaraju's strongly connected components algorithm
visit(graph, &visited);
/// </summary>
public void Kosaraju()
while (pop(NULL, &graph, &visited)) {
{
create(&assigned);
var L = new HashSet<Node>();
assign(graph, &assigned);
 
Action<Node> Visit = null;
if (assigned)
Visit = (u) =>
push(0, assigned, components);
{
}
if (u.color == Node.Colors.White)
}
{
u.color = Node.Colors.Gray;
 
foreach (var v in Adj[u])
Visit(v);
 
L.Add(u);
}
};
 
Action<Node, Node> Assign = null;
Assign = (u, root) =>
{
if (u.color != Node.Colors.Black)
{
if (u == root)
Console.Write("SCC: ");
 
Console.Write(u.N + " ");
u.color = Node.Colors.Black;
 
foreach (var v in Adj[u])
Assign(v, root);
 
if (u == root)
Console.WriteLine();
}
};
 
foreach (var u in V)
Visit(u);
 
foreach (var u in L)
Assign(u, u);
}
}</syntaxhighlight>
 
int main()
{
struct graph nodes[16];
struct graph *graph;
struct stack *component;
struct stack *components;
int lengths[7] = { 8, 6, 1, 6, 4, 1, 1 };
int offsets[7][9] = {
{ 0, 1, 2, 0, 3, 4, 0, 5, 7 },
{ 0, 9, 10, 11, 12, 9, 11 },
{ 1, 12 },
{ 3, 5, 6, 7, 8, 6, 15 },
{ 5, 13, 14, 13, 15 },
{ 8, 15 },
{ 10, 13 }
};
for (int i = 0; i < 16; i++) {
nodes[i].value = i;
nodes[i].state = 0;
create(&nodes[i].incoming);
create(&nodes[i].outgoing);
}
for (int i = 0; i < 7; i++)
path(lengths[i], offsets[i], nodes);
create(&components);
kosaraju(&nodes[0], &components);
while (pop(NULL, &component, &components)) {
while (pop(NULL, &graph, &component))
printf("%d ", graph->value);
printf("\n");
}
for (int i = 0; i < 16; i++) {
destroy(&nodes[i].incoming);
destroy(&nodes[i].outgoing);
}
}>/lang>
{{out}}
<pre>15
14 13
10 11 12 9
7 8 6
5
3 4 1 2 0
</pre>
=={{header|C++}}==
{{trans|D}}
<langsyntaxhighlight lang="cpp">#include <functional>
#include <iostream>
#include <ostream>
Line 273 ⟶ 224:
 
return 0;
}</langsyntaxhighlight>
{{out}}
<pre>[0, 0, 0, 3, 3, 5, 5, 7]</pre>
 
=={{header|C sharp|C#}}==
<lang csharp>using System;
using System.Collections.Generic;
 
class Node
{
public enum Colors
{
Black, White, Gray
}
 
public Colors color { get; set; }
public int N { get; }
public Node(int n)
{
N = n;
color = Colors.White;
}
}
 
class Graph
{
public HashSet<Node> V { get; }
public Dictionary<Node, HashSet<Node>> Adj { get; }
 
/// <summary>
/// Kosaraju's strongly connected components algorithm
/// </summary>
public void Kosaraju()
{
var L = new HashSet<Node>();
 
Action<Node> Visit = null;
Visit = (u) =>
{
if (u.color == Node.Colors.White)
{
u.color = Node.Colors.Gray;
 
foreach (var v in Adj[u])
Visit(v);
 
L.Add(u);
}
};
 
Action<Node, Node> Assign = null;
Assign = (u, root) =>
{
if (u.color != Node.Colors.Black)
{
if (u == root)
Console.Write("SCC: ");
 
Console.Write(u.N + " ");
u.color = Node.Colors.Black;
 
foreach (var v in Adj[u])
Assign(v, root);
 
if (u == root)
Console.WriteLine();
}
};
 
foreach (var u in V)
Visit(u);
 
foreach (var u in L)
Assign(u, u);
}
}</lang>
 
=={{header|D}}==
{{trans|Kotlin}} (mostly) with output like {{trans|Go}}
<langsyntaxhighlight Dlang="d">import std.container.array;
import std.stdio;
 
Line 419 ⟶ 296:
void main() {
writeln(kosaraju(g));
}</langsyntaxhighlight>
{{out}}
<pre>[0, 0, 0, 3, 3, 5, 5, 7]</pre>
=={{header|Delphi}}==
{{libheader| System.SysUtils}}
{{Trans|Go}}
<syntaxhighlight lang="delphi">
program KosarajuApp;
 
uses
System.SysUtils;
 
type
TKosaraju = TArray<TArray<Integer>>;
 
var
g: TKosaraju;
 
procedure Init();
begin
SetLength(g, 8);
g[0] := [1];
g[1] := [2];
g[2] := [0];
g[3] := [1, 2, 4];
g[4] := [3, 5];
g[5] := [2, 6];
g[6] := [5];
g[7] := [4, 6, 7];
end;
 
procedure Println(vector: TArray<Integer>);
var
i: Integer;
begin
write('[');
if (Length(vector) > 0) then
for i := 0 to High(vector) do
begin
write(vector[i]);
if (i < high(vector)) then
write(', ');
end;
 
writeln(']');
end;
 
function Kosaraju(g: TKosaraju): TArray<Integer>;
var
vis: TArray<Boolean>;
L, c: TArray<Integer>;
x: Integer;
t: TArray<TArray<Integer>>;
Visit: TProc<Integer>;
u: Integer;
Assign: TProc<Integer, Integer>;
begin
// 1. For each vertex u of the graph, mark u as unvisited. Let L be empty.
SetLength(vis, Length(g));
SetLength(L, Length(g));
x := Length(L);
// index for filling L in reverse order
SetLength(t, Length(g)); // transpose graph
 
// 2. recursive subroutine:
 
Visit := procedure(u: Integer)
begin
if (not vis[u]) then
begin
vis[u] := true;
for var v in g[u] do
begin
Visit(v);
t[v] := concat(t[v], [u]);
// construct transpose
end;
 
dec(x);
L[x] := u;
end;
end;
 
// 2. For each vertex u of the graph do Visit(u)
 
for u := 0 to High(g) do
begin
Visit(u);
end;
 
SetLength(c, Length(g)); // result, the component assignment
 
// 3: recursive subroutine:
 
Assign := procedure(u, root: Integer)
begin
if vis[u] then
// repurpose vis to mean "unassigned"
begin
vis[u] := false;
c[u] := root;
 
for var v in t[u] do
Assign(v, root);
end;
end;
 
// 3: For each element u of L in order, do Assign(u,u)
 
for u in L do
Assign(u, u);
 
Result := c;
end;
 
begin
Init;
Println(Kosaraju(g));
end.</syntaxhighlight>
{{out}}
<pre>[0, 0, 0, 3, 3, 5, 5, 7]</pre>
 
=={{header|Go}}==
<langsyntaxhighlight lang="go">package main
 
import "fmt"
Line 483 ⟶ 478:
}
return c
}</langsyntaxhighlight>
{{out}}
<pre>
[0 0 0 3 3 5 5 7]
</pre>
 
=={{header|J}}==
 
Implementation:
<syntaxhighlight lang="j">kosaraju=: {{
coerase([cocurrent)cocreate''
visit=: {{
if.y{unvisited do.
unvisited=: 0 y} unvisited
visit y{::out
L=: y,L
end.
}}"0
assign=: {{
if._1=y{assigned do.
assigned=: x y} assigned
x&assign y{::in
end.
}}"0
out=: y
in=: <@I.|:y e.S:0~i.#y
unvisited=: 1#~#y
assigned=: _1#~#y
L=: i.0
visit"0 i.#y
assign~L
assigned
}}</syntaxhighlight>
 
Task example (tree representation: each value here is the index of the parent node):
 
<syntaxhighlight lang="j"> kosaraju 1;2;0;1 2 4;3 5;2 6;5;4 6 7
0 0 0 3 3 5 5 7</syntaxhighlight>
 
Alternatively, we could represent the result as a graph of the same type as our argument graph. The implementation of <tt>visit</tt> remains the same:
 
<syntaxhighlight lang="j">kosarajud=: {{
coerase([cocurrent)cocreate''
visit=: {{
if.y{unvisited do.
unvisited=: 0 y} unvisited
visit y{::out
L=: y,L
end.
}}"0
assign=: {{
if.-.y e.;assigned do.
assigned=: (y,L:0~x{assigned) x} assigned
x&assign y{::in
end.
}}"0
out=: y
in=: <@I.|:y e.S:0~i.#y
unvisited=: 1#~#y
assigned=: a:#~#y
L=: i.0
visit"0 i.#y
assign~L
assigned
}}
 
kosarajud 1;2;0;1 2 4;3 5;2 6;5;4 6 7
┌─────┬┬┬───┬┬───┬┬─┐
│0 2 1│││3 4││5 6││7│
└─────┴┴┴───┴┴───┴┴─┘
</syntaxhighlight>
 
But it would probably be simpler to convert the result from the tree representation to our directed graph representation:
 
<syntaxhighlight lang="j"> ((<@I.@e."1 0)i.@#) 0 0 0 3 3 5 5 7
┌─────┬┬┬───┬┬───┬┬─┐
│0 1 2│││3 4││5 6││7│
└─────┴┴┴───┴┴───┴┴─┘</syntaxhighlight>
 
=={{header|Java}}==
{{trans|Kotlin}}
Output is like Go instead of what Kotlin outputs.
<langsyntaxhighlight lang="java">import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
Line 578 ⟶ 646:
System.out.println(output);
}
}</langsyntaxhighlight>
{{out}}
<pre>[0, 0, 0, 3, 3, 5, 5, 7]</pre>
 
=={{header|jq}}==
{{trans|Go}}
<syntaxhighlight lang="jq">
# Fill an array of the specified length with the input value
def dimension($n): . as $in | [range(0;$n) | $in];
 
# $graph should be an adjacency-list graph with IO==0
def korasaju($graph):
($graph|length) as $length
| def init: {
vis: (false | dimension($length)), # visited
L: [], # for an array of $length integers
t: ([]|dimension($length)), # transposed graph
x: $length # index
};
 
# input: {vis, L, t, x, t}
def visit($u):
if .vis[$u] | not
then .vis[$u] = true
| reduce ($graph[$u][]) as $v (.;
visit($v)
| .t[$v] += [$u] )
| .x -= 1
| .L[.x] = $u
else .
end ;
 
# input: {vis, t, c}
def assign($u; $root):
if .vis[$u]
then .vis[$u] = false
| .c[$u] = $root
| reduce .t[$u][] as $v (.; assign($v; $root))
else .
end ;
 
# For each vertex u of the graph, mark u as unvisited.
init
 
# For each vertex u of the graph do visit(u)
| reduce range(0;$length) as $u (.; visit($u))
| .c = (null|dimension($length))
 
# For each element u of L in order, do assign(u, u)
| reduce .L[] as $u (.; assign($u; $u) )
| .c ;
 
# An example adjacency list using IO==1
def g: [
[1],
[2],
[0],
[1, 2, 4],
[3, 5],
[2, 6],
[5],
[4, 6, 7]
];
 
korasaju(g)</syntaxhighlight>
{{out}}
With the jq program above in korasaju.jq, the invocation `jq -nc -f korasaju.jq` produces:
<syntaxhighlight lang="sh">
[0,0,0,3,3,5,5,7]
</syntaxhighlight>
 
=={{header|Julia}}==
Line 586 ⟶ 721:
{{trans|Go}}
 
<langsyntaxhighlight lang="julia">function korasaju(g::Vector{Vector{T}}) where T<:Integer
# 1. For each vertex u of the graph, mark u as unvisited. Let L be empty.
vis = falses(length(g))
Line 628 ⟶ 763:
 
g = [[2], [3], [1], [2, 3, 5], [4, 6], [3, 7], [6], [5, 7, 8]]
println(korasaju(g))</langsyntaxhighlight>
 
{{out}}
<pre>[1, 1, 1, 4, 4, 6, 6, 8]</pre>
 
=={{header|K}}==
{{works with|ngn/k}}
<syntaxhighlight lang=K>F:{[g] / graph
n: #g / number of vertices
v::&n / visited?
L::!0 / dfs order
V: {[g;x] $[v x;;[v[x]:1;o[g]'g x;L::x,L]];}[g]
V'!n / Visit
G: @[n#,!0;g;,;!n] / transposed graph
c::n#-1 / assigned components
A: {[G;x;y] $[-1=c x;[c[x]:y;G[x]o[G]'y];]}[G]'
A'/2#,L / Assign
.=c}</syntaxhighlight>
<syntaxhighlight lang=K> F(1;2;0;1 2 4;3 5;2 6;5;4 6 7)
(0 1 2
3 4
5 6
,7)</syntaxhighlight>
 
Alternative implementation, without global assignments:
 
<syntaxhighlight lang=K>F:{[g] /graph
n:#g /number of vertices
G:@[n#,!0;g;,;!n] /transposed graph
V:{[g;L;x]$[^L?x;(1_(x,L)o[g]/g x),x;L]}[g]
L:|V/[!0;!#g] /Visit
A:{[G;c;u;r]$[0>c u;o[G]/[@[c;u;:;r];G u;r];c]}[G]
.=A/[n#-1;L;L]} /Assign</syntaxhighlight>
 
(result is the same)
 
{{works with|Kona}}<syntaxhighlight lang=K>F:{[g] / graph
n: #g / number of vertices
v::&n / visited?
L::!0 / dfs order
V: {[g;x] :[v x;;[v[x]:1;_f[g]'g x;L::x,L]];}[g]
V'!n / Visit
G: @[n#,!0;g;,;!n] / transposed graph
c::n#-1 / assigned components
A: {[G;x;y] :[-1=c x;[c[x]:y;G[x]_f[G]'y];]}[G]'
A'/2#,L / Assign
.=c}</syntaxhighlight>
 
(result is the same)
 
=={{header|Kotlin}}==
{{trans|Go}}
<langsyntaxhighlight lang="scala">// version 1.1.3
 
/* the list index is the first vertex in the edge(s) */
Line 693 ⟶ 873:
fun main(args: Array<String>) {
println(kosaraju(g).joinToString("\n"))
}</langsyntaxhighlight>
 
{{out}}
Line 705 ⟶ 885:
=={{header|Lua}}==
{{trans|C++}}
<langsyntaxhighlight lang="lua">function write_array(a)
io.write("[")
for i=0,#a do
Line 799 ⟶ 979:
 
write_array(kosaraju(g))
print()</langsyntaxhighlight>
{{out}}
<pre>[0, 0, 0, 3, 3, 5, 5, 7]</pre>
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<syntaxhighlight lang="mathematica">g = Graph[{0 -> 1, 1 -> 2, 2 -> 0, 3 -> 1, 3 -> 2, 3 -> 4, 4 -> 3,
4 -> 5, 5 -> 2, 5 -> 6, 6 -> 5, 7 -> 4, 7 -> 6, 7 -> 7}];
cc = ConnectedComponents[g]
Catenate[ConstantArray[Min[#], Length[#]] & /@ SortBy[cc, First]]</syntaxhighlight>
{{out}}
<pre>{{0, 1, 2}, {5, 6}, {3, 4}, {7}}
{0, 0, 0, 3, 3, 5, 5, 7}</pre>
 
=={{header|Nim}}==
{{trans|Kotlin}}
<syntaxhighlight lang="nim">type
Vertex = int
Graph = seq[seq[Vertex]]
Scc = seq[Vertex]
 
func korasaju(g: Graph): seq[Scc] =
 
var
size = g.len
visited = newSeq[bool](size) # All false by default.
l = newSeq[Vertex](size) # All zero by default.
x = size # Index for filling "l" in reverse order.
t = newSeq[seq[Vertex]](size) # Transposed graph.
c = newSeq[Vertex](size) # Used for component assignment.
 
func visit(u: Vertex) =
if not visited[u]:
visited[u] = true
for v in g[u]:
visit(v)
t[v].add(u) # Construct transposed graph.
dec x
l[x] = u
 
func assign(u, root: Vertex) =
if visited[u]:
# Repurpose visited to mean 'unassigned'.
visited[u] = false
c[u] = root
for v in t[u]: v.assign(root)
 
for u in 0..g.high: u.visit()
for u in l: u.assign(u)
 
# Build list of strongly connected components.
var prev = -1
for v1, v2 in c:
if v2 != prev:
prev = v2
result.add @[]
result[^1].add v1
 
 
when isMainModule:
let g = @[@[1], @[2], @[0], @[1, 2, 4], @[3, 5], @[2, 6], @[5], @[4, 6, 7]]
for scc in korasaju(g): echo $scc</syntaxhighlight>
 
{{out}}
<pre>@[0, 1, 2]
@[3, 4]
@[5, 6]
@[7]</pre>
 
=={{header|Pascal}}==
Works with FPC (tested with version 3.2.2).
<syntaxhighlight lang="pascal">
program Kosaraju_SCC;
{$mode objfpc}{$modeswitch arrayoperators}
{$j-}{$coperators on}
type
TDigraph = array of array of Integer;
 
procedure PrintComponents(const g: TDigraph);
var
Visited: array of Boolean = nil;
RevPostOrder: array of Integer = nil;
gr: TDigraph = nil; //reversed graph
Counter, Next: Integer;
FirstItem: Boolean;
 
procedure Dfs1(aNode: Integer);
begin
Visited[aNode] := True;
for Next in g[aNode] do begin
gr[Next] += [aNode];
if not Visited[Next] then
Dfs1(Next);
end;
RevPostOrder[Counter] := aNode;
Dec(Counter);
end;
 
procedure Dfs2(aNode: Integer);
begin
Visited[aNode] := True;
for Next in gr[aNode] do
if not Visited[Next] then
Dfs2(Next);
if FirstItem then begin
FirstItem := False;
Write(aNode);
end else
Write(', ', aNode);
end;
 
var
Node: Integer;
begin
SetLength(Visited, Length(g));
SetLength(RevPostOrder, Length(g));
SetLength(gr, Length(g));
Counter := High(g);
for Node := 0 to High(g) do
if not Visited[Node] then
Dfs1(Node);
FillChar(Pointer(Visited)^, Length(Visited), 0);
for Node in RevPostOrder do
if not Visited[Node] then begin
FirstItem := True;
Write('[');
Dfs2(Node);
WriteLn(']');
end;
end;
 
const
g: TDigraph = (
(1),
(2),
(0),
(1, 2, 4),
(3, 5),
(2, 6),
(5),
(4, 6, 7)
);
begin
PrintComponents(g);
end.
</syntaxhighlight>
{{out}}
<pre>
[7]
[4, 3]
[6, 5]
[1, 2, 0]
</pre>
 
=={{header|Perl}}==
{{trans|Perl 6Raku}}
<langsyntaxhighlight lang="perl">use strict;
use warnings;
use feature 'say';
Line 875 ⟶ 1,203:
kosaraju(%test1);
say '';
kosaraju(%test2);</langsyntaxhighlight>
{{out}}
<pre>0 1 2
Line 886 ⟶ 1,214:
Fred Gary
Hank</pre>
 
=={{header|Perl 6}}==
{{works with|Rakudo|2018.09}}
Inspired by Python & Kotlin entries.
 
Accepts a hash of lists/arrays holding the vertex (name => (neighbors)) pairs. No longer limited to continuous, positive, integer vertex names.
 
<lang perl6>sub kosaraju (%k) {
my %g = %k.keys.sort Z=> flat ^%k;
my %h = %g.invert;
my %visited;
my @stack;
my @transpose;
my @connected;
sub visit ($u) {
unless %visited{$u} {
%visited{$u} = True;
for |%k{$u} -> $v {
visit($v);
@transpose[%g{$v}].push: $u;
}
@stack.push: $u;
}
}
sub assign ($u, $root) {
if %visited{$u} {
%visited{$u} = False;
@connected[%g{$u}] = $root;
assign($_, $root) for |@transpose[%g{$u}];
}
}
.&visit for %g.keys;
assign($_, $_) for @stack.reverse;
 
(|%g{@connected}).pairs.categorize( *.value, :as(*.key) ).values.map: { %h{|$_} };
}
 
# TESTING
 
-> $test { say "\nStrongly connected components: ", |kosaraju($test).sort } for
 
# Same test data as all other entries, converted to a hash of lists
(((1),(2),(0),(1,2,4),(3,5),(2,6),(5),(4,6,7)).pairs.hash),
 
# Same layout test data with named vertices instead of numbered.
(
%(:Andy<Bart>,
:Bart<Carl>,
:Carl<Andy>,
:Dave<Bart Carl Earl>,
:Earl<Dave Fred>,
:Fred<Carl Gary>,
:Gary<Fred>,
:Hank<Earl Gary Hank>)
)</lang>
{{out}}
<pre>
Strongly connected components: (0 1 2)(3 4)(5 6)(7)
 
Strongly connected components: (Andy Bart Carl)(Dave Earl)(Fred Gary)(Hank)</pre>
 
=={{header|Phix}}==
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>sequence visited, l, t, c
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
 
procedure visit(sequence g, integer u)
if not visited[u] then
visited[u] = true
for i=1 to length(g[u]) do
integer v = g[u][i]
visit(g,v)
t[v] &= u
end for
l &= u
end if
end procedure
 
procedure assign(integer u, root=u)
if visited[u] then
visited[u] = false
c[u] = root
for v=1 to length(t[u]) do
assign(t[u][v], root)
end for
end if
end procedure
 
function korasaju(sequence g)
integer len = length(g)
visited = repeat(false,len)
l = {}
t = repeat({},len)
for u=1 to len do
visit(g,u)
end for
c = repeat(0,len)
for u=length(l) to 1 by -1 do
assign(l[u])
end for
return c
end function
<span style="color: #004080;">sequence</span> <span style="color: #000000;">visited</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">l</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">t</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">c</span>
constant g = {{2}, {3}, {1}, {2, 3, 5}, {4, 6}, {3, 7}, {6}, {5, 7, 8}}
?korasaju(g)</lang>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">visit</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">g</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">u</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #008080;">not</span> <span style="color: #000000;">visited</span><span style="color: #0000FF;">[</span><span style="color: #000000;">u</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">visited</span><span style="color: #0000FF;">[</span><span style="color: #000000;">u</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">true</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">g</span><span style="color: #0000FF;">[</span><span style="color: #000000;">u</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">do</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">v</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">g</span><span style="color: #0000FF;">[</span><span style="color: #000000;">u</span><span style="color: #0000FF;">][</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #000000;">visit</span><span style="color: #0000FF;">(</span><span style="color: #000000;">g</span><span style="color: #0000FF;">,</span><span style="color: #000000;">v</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">t</span><span style="color: #0000FF;">[</span><span style="color: #000000;">v</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t</span><span style="color: #0000FF;">[</span><span style="color: #000000;">v</span><span style="color: #0000FF;">])</span> <span style="color: #0000FF;">&</span> <span style="color: #000000;">u</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">l</span> <span style="color: #0000FF;">&=</span> <span style="color: #000000;">u</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">assign</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">u</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">root</span><span style="color: #0000FF;">=</span><span style="color: #000000;">u</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">visited</span><span style="color: #0000FF;">[</span><span style="color: #000000;">u</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">visited</span><span style="color: #0000FF;">[</span><span style="color: #000000;">u</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span>
<span style="color: #000000;">c</span><span style="color: #0000FF;">[</span><span style="color: #000000;">u</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">root</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">v</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t</span><span style="color: #0000FF;">[</span><span style="color: #000000;">u</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">assign</span><span style="color: #0000FF;">(</span><span style="color: #000000;">t</span><span style="color: #0000FF;">[</span><span style="color: #000000;">u</span><span style="color: #0000FF;">][</span><span style="color: #000000;">v</span><span style="color: #0000FF;">],</span> <span style="color: #000000;">root</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">korasaju</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">g</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">len</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">g</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">visited</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #004600;">false</span><span style="color: #0000FF;">,</span><span style="color: #000000;">len</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">l</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{}</span>
<span style="color: #000000;">t</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">({},</span><span style="color: #000000;">len</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">u</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">len</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">visit</span><span style="color: #0000FF;">(</span><span style="color: #000000;">g</span><span style="color: #0000FF;">,</span><span style="color: #000000;">u</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">len</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">u</span><span style="color: #0000FF;">=</span><span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">l</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">to</span> <span style="color: #000000;">1</span> <span style="color: #008080;">by</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">assign</span><span style="color: #0000FF;">(</span><span style="color: #000000;">l</span><span style="color: #0000FF;">[</span><span style="color: #000000;">u</span><span style="color: #0000FF;">])</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">c</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">g</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">3</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">6</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">7</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">6</span><span style="color: #0000FF;">},</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">7</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">8</span><span style="color: #0000FF;">}}</span>
<span style="color: #0000FF;">?</span><span style="color: #000000;">korasaju</span><span style="color: #0000FF;">(</span><span style="color: #000000;">g</span><span style="color: #0000FF;">)</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Line 998 ⟶ 1,267:
 
=={{header|Python}}==
Works with Python 2
<lang python>def kosaraju(g):
<syntaxhighlight lang="python">def kosaraju(g):
class nonlocal: pass
 
Line 1,037 ⟶ 1,307:
 
g = [[1], [2], [0], [1,2,4], [3,5], [2,6], [5], [4,6,7]]
print kosaraju(g)</langsyntaxhighlight>
{{out}}
<pre>[0, 0, 0, 3, 3, 5, 5, 7]</pre>
 
Syntax requirements have changed. This version works with Python 3.
<syntaxhighlight lang="python3">def kosaraju(g):
size = len(g)
vis = [False] * size
l = [0] * size
x = size
t = [[] for _ in range(size)]
 
def visit(u):
nonlocal x
if not vis[u]:
vis[u] = True
for v in g[u]:
visit(v)
t[v].append(u)
x -= 1
l[x] = u
 
for u in range(size):
visit(u)
c = [0] * size
 
def assign(u, root):
if vis[u]:
vis[u] = False
c[u] = root
for v in t[u]:
assign(v, root)
 
for u in l:
assign(u, u)
 
return c
 
 
g = [[1], [2], [0], [1, 2, 4], [3, 5], [2, 6], [5], [4, 6, 7]]
print(kosaraju(g))</syntaxhighlight>
 
{{out}}
<pre>[0, 0, 0, 3, 3, 5, 5, 7]</pre>
 
 
=={{header|Racket}}==
<langsyntaxhighlight lang="racket">#lang racket
 
(require racket/dict)
Line 1,074 ⟶ 1,386:
(3 1 2 4) ; equvalent to (3 . (1 2 4))
(4 5 3)
(7 4 7 6))))</langsyntaxhighlight>
 
{{out}}
 
<pre>'((7) (6 5) (4 3) (2 1 0))</pre>
 
=={{header|Raku}}==
(formerly Perl 6)
{{works with|Rakudo|2018.09}}
Inspired by Python & Kotlin entries.
 
Accepts a hash of lists/arrays holding the vertex (name => (neighbors)) pairs. No longer limited to continuous, positive, integer vertex names.
 
<syntaxhighlight lang="raku" line>sub kosaraju (%k) {
my %g = %k.keys.sort Z=> flat ^%k;
my %h = %g.invert;
my %visited;
my @stack;
my @transpose;
my @connected;
sub visit ($u) {
unless %visited{$u} {
%visited{$u} = True;
for |%k{$u} -> $v {
visit($v);
@transpose[%g{$v}].push: $u;
}
@stack.push: $u;
}
}
sub assign ($u, $root) {
if %visited{$u} {
%visited{$u} = False;
@connected[%g{$u}] = $root;
assign($_, $root) for |@transpose[%g{$u}];
}
}
.&visit for %g.keys;
assign($_, $_) for @stack.reverse;
 
(|%g{@connected}).pairs.categorize( *.value, :as(*.key) ).values.map: { %h{|$_} };
}
 
# TESTING
 
-> $test { say "\nStrongly connected components: ", |kosaraju($test).sort } for
 
# Same test data as all other entries, converted to a hash of lists
(((1),(2),(0),(1,2,4),(3,5),(2,6),(5),(4,6,7)).pairs.hash),
 
# Same layout test data with named vertices instead of numbered.
(
%(:Andy<Bart>,
:Bart<Carl>,
:Carl<Andy>,
:Dave<Bart Carl Earl>,
:Earl<Dave Fred>,
:Fred<Carl Gary>,
:Gary<Fred>,
:Hank<Earl Gary Hank>)
)</syntaxhighlight>
{{out}}
<pre>
Strongly connected components: (0 1 2)(3 4)(5 6)(7)
 
Strongly connected components: (Andy Bart Carl)(Dave Earl)(Fred Gary)(Hank)</pre>
 
=={{header|Sidef}}==
{{trans|Julia}}
<langsyntaxhighlight lang="ruby">func korasaju(Array g) {
# 1. For each vertex u of the graph, mark u as unvisited. Let L be empty.
var vis = g.len.of(false)
Line 1,128 ⟶ 1,504:
 
var g = [[1], [2], [0], [1, 2, 4], [3, 5], [2, 6], [5], [4, 6, 7]]
say korasaju(g)</langsyntaxhighlight>
{{out}}
<pre>
Line 1,135 ⟶ 1,511:
 
=={{header|Standard ML}}==
<langsyntaxhighlight lang="sml">datatype 'a node = Node of 'a * bool ref * 'a node list ref * 'a node list ref
 
fun node x = Node (x, ref false, ref nil, ref nil)
Line 1,175 ⟶ 1,551:
fun assigns (xs, nil) = xs
| assigns (xs, n :: ns) =
if unmark n then
case assign (nil, (n :: nil) :: nil) of
let
nil => assigns (xs, ns)
| val x => assignssources (xn :: xs, ns)nil
val x = value n :: assign (nil, x)
in
assigns (x :: xs, ns)
end
else
assigns (xs, ns)
 
fun kosaraju xs = assigns (nil, visit (nil, Many xs :: nil))
Line 1,194 ⟶ 1,576:
val is = 0 :: nil
val ijs =
[0, 1, 2, 30, 43, 24, 0, 5, 7] ::
[0, 9, 10, 11, 12, 9, 11] ::
[1, 12] ::
Line 1,204 ⟶ 1,586:
 
val ns = make (16, is, ijs)
val xs = kosaraju ns</syntaxhighlight>
</lang>
{{out}}
<pre>
> xs;
val it = [[15], [1413, 1314], [9, 10, 11, 12, 9], [76, 87, 68], [5], [10, 31, 42, 23, 04]]: int list list
</pre>
 
Line 1,216 ⟶ 1,597:
{{trans|D}}
 
<langsyntaxhighlight lang="swift">func kosaraju(graph: [[Int]]) -> [Int] {
let size = graph.count
var x = size
Line 1,275 ⟶ 1,656:
]
 
print(kosaraju(graph: graph))</langsyntaxhighlight>
 
{{out}}
 
<pre>[0, 0, 0, 3, 3, 5, 5, 7]</pre>
 
=={{header|Visual Basic .NET}}==
{{trans|Java}}
<syntaxhighlight lang="vbnet">Module Module1
 
Function Kosaraju(g As List(Of List(Of Integer))) As List(Of Integer)
Dim size = g.Count
Dim vis(size - 1) As Boolean
Dim l(size - 1) As Integer
Dim x = size
 
Dim t As New List(Of List(Of Integer))
For i = 1 To size
t.Add(New List(Of Integer))
Next
 
Dim visit As Action(Of Integer) = Sub(u As Integer)
If Not vis(u) Then
vis(u) = True
For Each v In g(u)
visit(v)
t(v).Add(u)
Next
x -= 1
l(x) = u
End If
End Sub
 
For i = 1 To size
visit(i - 1)
Next
Dim c(size - 1) As Integer
 
Dim assign As Action(Of Integer, Integer) = Sub(u As Integer, root As Integer)
If vis(u) Then
vis(u) = False
c(u) = root
For Each v In t(u)
assign(v, root)
Next
End If
End Sub
 
For Each u In l
assign(u, u)
Next
 
Return c.ToList
End Function
 
Sub Main()
Dim g = New List(Of List(Of Integer)) From {
New List(Of Integer) From {1},
New List(Of Integer) From {2},
New List(Of Integer) From {0},
New List(Of Integer) From {1, 2, 4},
New List(Of Integer) From {3, 5},
New List(Of Integer) From {2, 6},
New List(Of Integer) From {5},
New List(Of Integer) From {4, 6, 7}
}
 
Dim output = Kosaraju(g)
Console.WriteLine("[{0}]", String.Join(", ", output))
End Sub
 
End Module</syntaxhighlight>
{{out}}
<pre>[0, 0, 0, 3, 3, 5, 5, 7]</pre>
 
=={{header|Wren}}==
{{trans|Go}}
<syntaxhighlight lang="wren">var kosaraju = Fn.new { |g|
var gc = g.count
// 1. For each vertex u of the graph, mark u as unvisited. Let l be empty.
var vis = List.filled(gc, false)
var l = List.filled(gc, 0)
var x = gc // index for filling l in reverse order
var t = List.filled(gc, null) // transpose graph
for (i in 0...gc) t[i] = []
var visit // recursive function
visit = Fn.new { |u|
if (!vis[u]) {
vis[u] = true
for (v in g[u]) {
visit.call(v)
t[v].add(u) // construct transpose
}
x = x - 1
l[x] = u
}
}
// 2. For each vertex u of the graph do visit.call(u).
for (i in 0...gc) visit.call(i)
var c = List.filled(gc, 0) // result, the component assignment
var assign // recursive function
assign = Fn.new { |u, root|
if (vis[u]) { // repurpose vis to mean 'unassigned'
vis[u] = false
c[u] = root
for (v in t[u]) assign.call(v, root)
}
}
// 3: For each element u of l in order, do assign.call(u,u).
for (u in l) assign.call(u, u)
return c
}
 
var g = [ [1], [2], [0], [1, 2, 4], [3, 5], [2, 6], [5], [4, 6, 7] ]
System.print(kosaraju.call(g))</syntaxhighlight>
 
{{out}}
<pre>
[0, 0, 0, 3, 3, 5, 5, 7]
</pre>
 
=={{header|zkl}}==
<langsyntaxhighlight lang="zkl">const VISITED=0,ASSIGNED=1;
 
fcn visit(u,G,L){ // u is ((visited,assigned), (id,edges))
Line 1,322 ⟶ 1,818:
 
return(components);
}</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl"> // graph from https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm
// with vertices id zero based (vs 1 based in article)
// ids start at zero and are consecutive (no holes), graph is unsorted
Line 1,329 ⟶ 1,825:
T( T(0,1), T(2,0), T(5,2,6), T(6,5),
T(1,2), T(3,1,2,4), T(4,5,3), T(7,4,7,6) );
kosaraju(graph);</langsyntaxhighlight>
{{out}}
<pre>
1,480

edits