#include #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); }