Files
cKit/Graph/c_Topological.c
T
2026-09-07 18:48:16 +08:00

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