#include c_err_t c_Digraph_Init(c_Digraph_t* self, c_size_t V, c_Allocator_t* alloc) { if (!self) return C_ERR_PARAM; /* 1. 复制或初始化分配器 */ self->allocator = alloc ? *alloc : c_DefaultAllocator; self->V = V; self->E = 0; self->adj_list = NULL; self->indegree = NULL; if (V > 0) { /* 2. 分配邻接表骨架内存 */ self->adj_list = (c_AdjList_t*)c_Allocator_Calloc(&self->allocator, V, sizeof(c_AdjList_t)); if (!self->adj_list) return C_ERR_NOMEM; /* 3. 分配入度计数数组内存 */ self->indegree = (c_size_t*)c_Allocator_Calloc(&self->allocator, V, sizeof(c_size_t)); if (!self->indegree) { c_Allocator_Free(&self->allocator, self->adj_list); self->adj_list = NULL; return C_ERR_NOMEM; } /* 4. 初始化每个顶点的邻接表 */ for (c_size_t i = 0; i < V; ++i) { c_AdjList_Init(&self->adj_list[i], 0, alloc); } } return C_SUCCESS; } void c_Digraph_Destroy(c_Digraph_t* self) { if (!self) return; if (self->adj_list) { for (c_size_t i = 0; i < self->V; ++i) { c_AdjList_Destroy(&self->adj_list[i]); } c_Allocator_Free(&self->allocator, self->adj_list); self->adj_list = NULL; } if (self->indegree) { c_Allocator_Free(&self->allocator, self->indegree); self->indegree = NULL; } self->V = 0; self->E = 0; } c_err_t c_Digraph_AddEdge(c_Digraph_t* self, c_size_t from, c_size_t to) { if (!self || from >= self->V || to >= self->V) { return C_ERR_PARAM; } /* 往 from 节点的邻接表末尾追加 to 节点 */ c_err_t err = c_AdjList_Append(&self->adj_list[from], (c_uint_t)to); if (err == C_SUCCESS) { self->E++; self->indegree[to]++; /* O(1) 同步更新入度计数 */ } return err; } c_err_t c_Digraph_Resize(c_Digraph_t* self, c_size_t new_V) { if (!self) return C_ERR_PARAM; if (new_V == self->V) return C_SUCCESS; if (new_V == 0) { c_Digraph_Destroy(self); return C_SUCCESS; } /* 1. 如果新尺寸变小,需先释放多余顶点的数组资源 */ if (new_V < self->V) { for (c_size_t i = new_V; i < self->V; ++i) { /* 注意:如果被删除的顶点包含出边,可能会导致其他顶点的入度不准确 */ /* 健壮的做法是在销毁前遍历这些出边,给对应目标的入度做减法 */ c_AdjList_t* adj = &self->adj_list[i]; c_size_t size = (c_size_t)c_AdjList_GetSize(adj); for (c_size_t j = 0; j < size; ++j) { c_size_t target; if (c_AdjList_Get(adj, j, &target)!=C_ERR_OK) { continue; } if (target < new_V) { self->indegree[target]--; self->E--; } } c_AdjList_Destroy(&self->adj_list[i]); } } /* 2. 重新调整邻接表骨架内存空间 */ c_AdjList_t* new_list = (c_AdjList_t*)c_Allocator_Realloc( &self->allocator, self->adj_list, self->V * sizeof(c_AdjList_t), new_V * sizeof(c_AdjList_t) ); if (!new_list) return C_ERR_NOMEM; self->adj_list = new_list; /* 3. 重新调整入度数组内存空间 */ c_size_t* new_indegree = (c_size_t*)c_Allocator_Realloc( &self->allocator, self->indegree, self->V * sizeof(c_size_t), new_V * sizeof(c_size_t) ); if (!new_indegree) return C_ERR_NOMEM; self->indegree = new_indegree; /* 4. 如果新尺寸变大,初始化新增加顶点的邻接表与入度计数 */ if (new_V > self->V) { for (c_size_t i = self->V; i < new_V; ++i) { memset(&self->adj_list[i], 0, sizeof(c_AdjList_t)); c_AdjList_Init(&self->adj_list[i], 0, &self->allocator); self->indegree[i] = 0; } } self->V = new_V; return C_SUCCESS; } c_size_t c_Digraph_GetDegree(c_Digraph_t* self, c_size_t v, c_bool_t out_degree_only) { if (!self || v >= self->V) return 0; /* 1. 出度 (Out-Degree):直接获取该顶点邻接表的元素数量 */ if (out_degree_only) { return (c_size_t)c_AdjList_GetSize(&self->adj_list[v]); } /* 2. 入度 (In-Degree):需要遍历整个图,统计有多少条边指向 v */ return self->indegree[v]; } c_err_t c_Digraph_Reverse(c_Digraph_t* self, c_Digraph_t* out_reversed) { if (!self || !out_reversed) return C_ERR_PARAM; c_err_t err = c_Digraph_Init(out_reversed, self->V, &self->allocator); if (err != C_SUCCESS) return err; for (c_size_t u = 0; u < self->V; ++u) { c_AdjList_t* adj = &self->adj_list[u]; c_size_t size = (c_size_t)c_AdjList_GetSize(adj); for (c_size_t i = 0; i < size; ++i) { c_size_t v; if (c_AdjList_Get(adj, i, &v)!=C_ERR_OK) { continue; } err = c_Digraph_AddEdge(out_reversed, v, u); if (err != C_SUCCESS) { c_Digraph_Destroy(out_reversed); return err; } } } return C_SUCCESS; } /* ================================================================================================================== */ /* Unweighted Digraph Edge Query Primitive */ c_err_t c_Digraph_GetEdge(c_Digraph_t* self, c_size_t from, c_size_t to, c_size_t * edge_idx) { if (!self ) return C_ERR_PARAM; if (from >= self->V) return C_ERR_OUTOFBOUND; c_AdjList_t* adj = &self->adj_list[from]; c_size_t size = (c_size_t)c_UIntArray_GetSize(adj); c_uint_t target_value = 0; for (c_size_t i=0; i= self->V || to >= self->V) return C_ERR_OUTOFBOUND; c_AdjList_t* adj = &self->adj_list[from]; c_size_t size = (c_size_t)c_UIntArray_GetSize(adj); c_bool_t found = C_FALSE; /* Locate the target destination 'to' inside the out-list array */ for (c_size_t i = 0; i < size; ++i) { c_uint_t generic_entry = 0; if (c_UIntArray_Get(adj, i, &generic_entry) == C_SUCCESS) { if ((c_size_t)generic_entry == to) { /* Remove the entry element via your underlying array interface */ c_UIntArray_Remove(adj, i); found = C_TRUE; break; } } } if (found) { if (self->E > 0) self->E--; self->indegree[to]--; return C_SUCCESS; } return C_ERR_NOTFOUND; } c_bool_t c_Digraph_HasEdge(const c_Digraph_t* self, c_size_t from, c_size_t to) { if (!self || from >= self->V || to >= self->V) return C_FALSE; const c_AdjList_t* adj = &self->adj_list[from]; c_size_t size = (c_size_t)c_UIntArray_GetSize((c_UIntArray_t*)adj); /* Scan the adjacency out-list of vertex 'from' */ for (c_size_t i = 0; i < size; ++i) { c_uint_t generic_val = 0; /* Safely extract the adjacent vertex using your pointer specifications */ c_err_t err = c_UIntArray_Get((c_UIntArray_t*)adj, i, &generic_val); if (err == C_SUCCESS && (c_size_t)generic_val == to) { return C_TRUE; /* Edge found */ } } return C_FALSE; /* Edge does not exist */ }