#include #include typedef struct { c_size_t v; /* Current vertex */ c_size_t edge_idx; /* Next neighbor index to examine in the adjacency list */ } c_DFSFrame_t; c_err_t c_NonrecursiveDirectedDFS_Init(c_NonrecursiveDirectedDFS_t* self, c_Digraph_t* graph, c_size_t s, c_Allocator_t* allocator) { if (!self || !graph || s >= graph->V) return C_ERR_PARAM; self->allocator = allocator?*allocator:c_DefaultAllocator; self->count = 0; /* 1. Allocate the visited tracking array */ self->marked = (c_bool_t*)c_Allocator_Calloc(&self->allocator, graph->V, sizeof(c_bool_t)); if (!self->marked) return C_ERR_NOMEM; /* 2. Allocate an explicit execution stack bounded exactly by the number of vertices O(V) */ c_DFSFrame_t frame={0}; c_ArrayStack_t stack; c_err_t err = c_ArrayStack_Init(&stack, sizeof(c_DFSFrame_t), 0, allocator); if (err!=C_ERR_OK) { c_Allocator_Free(&self->allocator, self->marked); self->marked = NULL; return err; } /* Push the initial source vertex frame onto our stack */ self->marked[s] = C_TRUE; self->count++; frame.v = s; frame.edge_idx = 0; c_ArrayStack_Push(&stack, &frame); /* 3. Non-recursive processing loop */ while (!c_ArrayStack_IsEmpty(&stack)) { /* Peek the top frame */ c_DFSFrame_t* current_frame = c_ArrayStack_Peek(&stack); c_size_t u = current_frame->v; c_AdjList_t* adj = &graph->adj_list[u]; c_size_t neighbor_count = (c_size_t)c_AdjList_GetSize(adj); /* Advance down the adjacency list until we find an unvisited neighbor or finish the list */ c_bool_t advanced = C_FALSE; while (current_frame->edge_idx < neighbor_count) { c_size_t w; c_AdjList_Get(adj, current_frame->edge_idx, &w); current_frame->edge_idx++; /* Increment pointer for next pass */ if (!self->marked[w]) { self->marked[w] = C_TRUE; self->count++; /* Push new frame onto the stack (equivalent to recursive call invocation) */ frame.v = w; frame.edge_idx = 0; c_ArrayStack_Push(&stack, &frame); advanced = C_TRUE; break; } } /* If we explored all neighbors of vertex u, pop it from the stack */ if (!advanced) { c_ArrayStack_Pop(&stack, 0); } } /* Clean up the runtime frame stack buffer */ c_ArrayStack_Destroy(&stack); return C_SUCCESS; } void c_NonrecursiveDirectedDFS_Destroy(c_NonrecursiveDirectedDFS_t* self) { if (!self) return; if (self->marked) { c_Allocator_Free(&self->allocator, self->marked); self->marked = NULL; } self->count = 0; }