5ac7e2d52da2590f1fc1c1ae9f3eee75a289b029
14 struct components
*next
;
24 static int ptrcmp(const void *l
, const void *r
)
26 return (ptrdiff_t)((struct node
*)l
)->data
27 - (ptrdiff_t)((struct node
*)r
)->data
;
30 static int nodecmp(const void *l
, const void *r
)
32 return (ptrdiff_t)l
-(ptrdiff_t)((struct node
*)r
)->data
;
35 struct components
*strongconnect(struct node
*v
, struct node
**stack
, int *sp
,
36 int *index
, int nedges
, struct edge
*edges
,
37 struct components
*res
, struct components
**tail
)
46 for (int i
= 0; i
<nedges
; i
++) {
47 //Only consider nodes reachable from v
48 if (edges
[i
].from
!= v
)
52 res
= strongconnect(w
, stack
, sp
, index
,
53 nedges
, edges
, res
, tail
);
55 v
->lowlink
= min(v
->lowlink
, w
->index
);
58 if (v
->lowlink
== v
->index
) {
59 struct components
*ng
= safe_malloc(sizeof(struct components
));
72 ng
->nodes
= safe_malloc(ng
->nnodes
*sizeof(void *));
73 for (int i
= 0; i
<ng
->nnodes
; i
++)
74 ng
->nodes
[i
] = stack
[*sp
+i
]->data
;
80 bsearch(key, nodes, nnodes, sizeof(struct node), nodecmp);\
82 fprintf(stderr, "edge references unknown node\n");\
86 struct components *scc(int nnodes, void **nodedata, int nedges, struct edge **edgedata)
89 struct node
*nodes
= safe_malloc(nnodes
*sizeof(struct node
));
90 for (int i
= 0; i
<nnodes
; i
++)
91 nodes
[i
] = (struct node
){.lowlink
=-1, .index
=-1,
92 .onStack
=false, .data
=nodedata
[i
]};
93 qsort(nodes
, nnodes
, sizeof(struct node
), ptrcmp
);
96 struct edge
*edges
= safe_malloc(nedges
*sizeof(struct edge
));
97 for (int i
= 0; i
<nedges
; i
++) {
98 struct node
*from
= nsearch(edgedata
[i
]->from
);
99 struct node
*to
= nsearch(edgedata
[i
]->to
);
100 edges
[i
] = (struct edge
){.from
=from
, .to
=to
};
104 struct components
*res
= NULL
, *tail
= NULL
;
105 struct node
**stack
= safe_malloc(nnodes
*sizeof(struct node
*));
108 for (int i
= 0; i
< nnodes
; i
++) {
109 if (nodes
[i
].index
== -1)
110 res
= strongconnect(&nodes
[i
], stack
, &sp
, &index
,
111 nedges
, edges
, res
, &tail
);
120 void components_free(struct components
*cs
, void (*freefun
)(void *))
124 for (int i
= 0; i
<cs
->nnodes
; i
++)
125 freefun(cs
->nodes
[i
]);
127 struct components
*t
= cs
->next
;