#include // Internal recursive helper function that tracks execution states down the stack frames static c_bool_t c_Graph_DFS_Internal( const c_Graph_t* self, c_size_t current_vertex, c_bool_t* visited, c_Graph_DFS_Callback callback, void* context) { // Mark node as discovered visited[current_vertex] = C_TRUE; // Execute user callback function. If it returns false, bubble up to trigger an early abort. if (callback && !callback(current_vertex, context)) { return C_FALSE; } const c_AdjList_t* neighbors = &self->adj_list[current_vertex]; // Cache-friendly sequential scan over the contiguous array of primitive integer neighbors for (c_size_t i = 0; i < neighbors->size; i++) { c_uint_t neighbor = neighbors->array[i]; if (!visited[neighbor]) { // Recurse into unvisited neighbors. Propagate abort commands immediately. if (!c_Graph_DFS_Internal(self, neighbor, visited, callback, context)) { return C_FALSE; } } } return C_TRUE; // Continue searching normally } c_err_t c_Graph_DFS(const c_Graph_t* self, c_size_t src_vertex, c_Graph_DFS_Callback callback, void* context, c_Allocator_t* allocator) { if (!self || src_vertex >= self->V) { return C_ERR_PARAM; } if (self->V == 0) { return C_SUCCESS; } allocator = allocator?allocator:&c_DefaultAllocator; // Allocate tracking memory via the graph's configured allocator c_bool_t* visited = (c_bool_t*)c_Allocator_Alloc(allocator, self->V * sizeof(c_bool_t)); if (!visited) { return C_ERR_NOMEM; } // Initialize all tracking slots to false memset(visited, 0, self->V * sizeof(c_bool_t)); // Launch the deep structural recursive traversal engine c_Graph_DFS_Internal(self, src_vertex, visited, callback, context); // Safely free the temporary visited array tracking memory bounds c_Allocator_Free(allocator, visited); return C_SUCCESS; }