53 lines
1.8 KiB
C
53 lines
1.8 KiB
C
#include <c_Topological.h>
|
|||
|
|
#include "c_DirectedCycle.h"
|
||
|
|
#include "c_DepthFirstOrder.h"
|
||
|
|
|
||
|
|
c_err_t c_Topological_Init(c_Topological_t* self, c_Digraph_t* graph, c_Allocator_t* allocator) {
|
||
|
|
if (!self || !graph) return C_ERR_PARAM;
|
||
|
|
|
||
|
|
self->allocator = allocator ? *allocator : c_DefaultAllocator;
|
||
|
|
self->has_order = C_FALSE;
|
||
|
|
c_VertexIdList_Init(&self->order, 0, allocator);
|
||
|
|
|
||
|
|
/* 1. Cycle Check: Verify the graph is a Directed Acyclic Graph (DAG) */
|
||
|
|
c_DirectedCycle_t cycle_detector;
|
||
|
|
c_err_t err = c_DirectedCycle_Init(&cycle_detector, graph, allocator);
|
||
|
|
if (err != C_SUCCESS) return err;
|
||
|
|
|
||
|
|
c_bool_t has_cycle = c_DirectedCycle_HasCycle(&cycle_detector);
|
||
|
|
c_DirectedCycle_Destroy(&cycle_detector);
|
||
|
|
|
||
|
|
/* If a cycle is present, it is not a DAG; skip order calculation and return success */
|
||
|
|
if (has_cycle) {
|
||
|
|
return C_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* 2. Compute Depth-First Order streams */
|
||
|
|
c_DepthFirstOrder_t dfs_order;
|
||
|
|
err = c_DepthFirstOrder_Init(&dfs_order, graph, allocator);
|
||
|
|
if (err != C_SUCCESS) return err;
|
||
|
|
|
||
|
|
/* 3. Extract the Reverse Post-Order stream directly using high-speed copy */
|
||
|
|
err = c_DepthFirstOrder_GetReversePost(&dfs_order, &self->order);
|
||
|
|
c_DepthFirstOrder_Destroy(&dfs_order);
|
||
|
|
|
||
|
|
if (err != C_SUCCESS) return err;
|
||
|
|
|
||
|
|
self->has_order = C_TRUE;
|
||
|
|
return C_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
void c_Topological_Destroy(c_Topological_t* self) {
|
||
|
|
if (!self) return;
|
||
|
|
c_VertexIdList_Destroy(&self->order);
|
||
|
|
self->has_order = C_FALSE;
|
||
|
|
}
|
||
|
|
|
||
|
|
c_err_t c_Topological_GetOrder(c_Topological_t* self, c_VertexIdList_t* out_order) {
|
||
|
|
if (!self || !out_order) return C_ERR_PARAM;
|
||
|
|
if (!self->has_order) return C_ERR_FAIL;
|
||
|
|
|
||
|
|
/* High-speed block copy of the pre-computed topological sequence */
|
||
|
|
return c_VertexIdList_Copy(out_order, (c_UIntArray_t*)&self->order);
|
||
|
|
}
|