This commit is contained in:
2026-09-07 18:48:16 +08:00
parent 1564716731
commit c945aa211f
138 changed files with 10337 additions and 150 deletions
+88
View File
@@ -0,0 +1,88 @@
#include <c_NonrecursiveDirectedDFS.h>
#include <c_ArrayStack.h>
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;
}