52 lines
1.7 KiB
C
52 lines
1.7 KiB
C
#include <c_TransitiveClosure.h>
|
|||
|
|
|
||
|
|
c_err_t c_TransitiveClosure_Init(c_TransitiveClosure_t* self, c_Digraph_t* graph, c_Allocator_t* allocator) {
|
||
|
|
if (!self || !graph) return C_ERR_PARAM;
|
||
|
|
|
||
|
|
self->allocator = allocator ? *allocator : c_DefaultAllocator;
|
||
|
|
self->V = graph->V;
|
||
|
|
self->dfs_matrix = NULL;
|
||
|
|
|
||
|
|
if (self->V == 0) return C_SUCCESS;
|
||
|
|
|
||
|
|
/* 1. Allocate an array of non-recursive DFS structures */
|
||
|
|
self->dfs_matrix = (c_NonrecursiveDirectedDFS_t*)c_Allocator_Calloc(
|
||
|
|
&self->allocator,
|
||
|
|
self->V,
|
||
|
|
sizeof(c_NonrecursiveDirectedDFS_t)
|
||
|
|
);
|
||
|
|
if (!self->dfs_matrix) return C_ERR_NOMEM;
|
||
|
|
|
||
|
|
/* 2. Run a non-recursive DFS starting from each individual vertex */
|
||
|
|
for (c_size_t v = 0; v < self->V; ++v) {
|
||
|
|
c_err_t err = c_NonrecursiveDirectedDFS_Init(&self->dfs_matrix[v], graph, v, allocator);
|
||
|
|
|
||
|
|
if (err != C_SUCCESS) {
|
||
|
|
/* Clean up previously initialized instances to avoid memory leaks if OOM occurs mid-way */
|
||
|
|
for (c_size_t i = 0; i < v; ++i) {
|
||
|
|
c_NonrecursiveDirectedDFS_Destroy(&self->dfs_matrix[i]);
|
||
|
|
}
|
||
|
|
c_Allocator_Free(&self->allocator, self->dfs_matrix);
|
||
|
|
self->dfs_matrix = NULL;
|
||
|
|
self->V = 0;
|
||
|
|
return err;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return C_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
void c_TransitiveClosure_Destroy(c_TransitiveClosure_t* self) {
|
||
|
|
if (!self) return;
|
||
|
|
|
||
|
|
if (self->dfs_matrix) {
|
||
|
|
/* Deallocate every independent tracking instance matrix block */
|
||
|
|
for (c_size_t i = 0; i < self->V; ++i) {
|
||
|
|
c_NonrecursiveDirectedDFS_Destroy(&self->dfs_matrix[i]);
|
||
|
|
}
|
||
|
|
c_Allocator_Free(&self->allocator, self->dfs_matrix);
|
||
|
|
self->dfs_matrix = NULL;
|
||
|
|
}
|
||
|
|
self->V = 0;
|
||
|
|
}
|