f399b843a0cc77f9040fdc83c507401f11f1c725
6 #define min(x, y) ((x)<(y) ? (x) : (y))
17 struct components
*next
;
33 struct components
*head
;
34 struct components
*tail
;
37 static int nodecmp(const void *l
, const void *r
)
39 return (ptrdiff_t)l
-(ptrdiff_t)((struct node
*)r
)->data
;
42 static int strongconnect(struct node
*v
, struct tjstate
*tj
)
46 /* Set the depth index for v to the smallest unused index */
48 v
->lowlink
= tj
->index
;
50 tj
->stack
[tj
->sp
] = v
;
54 for (int i
= 0; i
<tj
->nedges
; i
++) {
55 /* Only consider nodes reachable from v */
56 if (tj
->edges
[i
].from
!= v
) {
60 /* Successor w has not yet been visited; recurse on it */
62 int r
= strongconnect(w
, tj
);
65 v
->lowlink
= min(v
->lowlink
, w
->lowlink
);
66 /* Successor w is in stack S and hence in the current SCC */
67 } else if (w
->onStack
) {
68 v
->lowlink
= min(v
->lowlink
, w
->index
);
72 /* If v is a root node, pop the stack and generate an SCC */
73 if (v
->lowlink
== v
->index
) {
74 struct components
*ng
= malloc(sizeof(struct components
));
78 if (tj
->tail
== NULL
) {
88 w
= tj
->stack
[tj
->sp
];
92 ng
->nodes
= malloc(ng
->nnodes
*sizeof(void *));
96 for (int i
= 0; i
<ng
->nnodes
; i
++) {
97 ng
->nodes
[i
] = tj
->stack
[tj
->sp
+i
]->data
;
103 static int ptrcmp(const void *l
, const void *r
)
105 return (ptrdiff_t)((struct node
*)l
)->data
106 - (ptrdiff_t)((struct node
*)r
)->data
;
110 * Calculate the strongly connected components using Tarjan's algorithm:
111 * en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm
113 * Returns NULL when there are invalid edges and sets the error to:
114 * 1 if there was a malformed edge
117 * @param number of nodes
118 * @param data of the nodes
119 * @param number of edges
120 * @param data of edges
121 * @param pointer to error code
123 struct components
*tarjans(
124 int nnodes
, void *nodedata
[],
125 int nedges
, struct edge
*edgedata
[],
128 struct node nodes
[nnodes
];
129 struct edge edges
[nedges
];
130 struct node
*stack
[nnodes
];
131 struct node
*from
, *to
;
132 struct tjstate tj
= {0, 0, nedges
, edges
, stack
, NULL
, .tail
=NULL
};
134 // Populate the nodes
135 for (int i
= 0; i
<nnodes
; i
++) {
136 nodes
[i
] = (struct node
){-1, -1, false, nodedata
[i
]};
138 qsort(nodes
, nnodes
, sizeof(struct node
), ptrcmp
);
140 // Populate the edges
141 for (int i
= 0; i
<nedges
; i
++) {
142 from
= bsearch(edgedata
[i
]->from
, nodes
, nnodes
,
143 sizeof(struct node
), nodecmp
);
148 to
= bsearch(edgedata
[i
]->to
, nodes
, nnodes
,
149 sizeof(struct node
), nodecmp
);
154 edges
[i
] = (struct edge
){.from
=from
, .to
=to
};
158 for (int i
= 0; i
< nnodes
; i
++) {
159 if (nodes
[i
].index
== -1) {
160 *error
= strongconnect(&nodes
[i
], &tj
);
168 void components_free(struct components
*cs
, void (*freefun
)(void *))
170 struct components
*t
;
173 if (freefun
!= NULL
) {
174 for (int i
= 0; i
<cs
->nnodes
; i
++) {
175 freefun(cs
->nodes
[i
]);