156 lines
4.7 KiB
C
156 lines
4.7 KiB
C
#include <c_EdgeWeightedGraph.h>
|
|
|
|
c_err_t c_EdgeWeightedGraph_Init(c_EdgeWeightedGraph_t* self, c_size_t V, c_Allocator_t* alloc) {
|
|
if (!self) return C_ERR_PARAM;
|
|
|
|
self->allocator = alloc ? *alloc : c_DefaultAllocator;
|
|
self->V = V;
|
|
self->E = 0;
|
|
self->adj_list = NULL;
|
|
self->edges_pool = NULL;
|
|
self->edges_cap = 0;
|
|
|
|
if (V > 0) {
|
|
/* Allocate dynamic adjacency list managers matching V size */
|
|
self->adj_list = c_Allocator_Calloc(&self->allocator, V, sizeof(c_UIntArray_t));
|
|
if (!self->adj_list) return C_ERR_NOMEM;
|
|
|
|
for (c_size_t i = 0; i < V; ++i) {
|
|
c_AdjList_Init(&self->adj_list[i], 0, alloc);
|
|
}
|
|
}
|
|
|
|
return C_SUCCESS;
|
|
}
|
|
|
|
void c_EdgeWeightedGraph_Destroy(c_EdgeWeightedGraph_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->edges_pool) {
|
|
c_Allocator_Free(&self->allocator, self->edges_pool);
|
|
self->edges_pool = NULL;
|
|
}
|
|
|
|
self->V = 0;
|
|
self->E = 0;
|
|
self->edges_cap = 0;
|
|
}
|
|
|
|
c_err_t c_EdgeWeightedGraph_AddEdge(c_EdgeWeightedGraph_t* self, c_size_t v, c_size_t w, double weight) {
|
|
if (!self || v >= self->V || w >= self->V) return C_ERR_PARAM;
|
|
|
|
/* 1. Ensure the global edge pool buffer has enough memory capacity */
|
|
if (self->E >= self->edges_cap) {
|
|
c_size_t old_cap = self->edges_cap;
|
|
c_size_t new_cap = old_cap == 0 ? 4 : old_cap * 2;
|
|
|
|
c_Edge_t* new_pool = (c_Edge_t*)c_Allocator_Realloc(
|
|
&self->allocator,
|
|
self->edges_pool,
|
|
old_cap * sizeof(c_Edge_t),
|
|
new_cap * sizeof(c_Edge_t)
|
|
);
|
|
if (!new_pool) return C_ERR_NOMEM;
|
|
|
|
self->edges_pool = new_pool;
|
|
self->edges_cap = new_cap;
|
|
}
|
|
|
|
/* 2. Assign configuration details into the pool item slot */
|
|
c_size_t edge_id = self->E;
|
|
self->edges_pool[edge_id] = (c_Edge_t){ .v = v, .w = w, .weight = weight };
|
|
|
|
/* 3. Append the structural reference pointer id into BOTH adjacent endpoint tracking arrays */
|
|
c_err_t err = c_AdjList_Append(&self->adj_list[v], (c_uint_t)edge_id);
|
|
if (err != C_SUCCESS) return err;
|
|
|
|
err = c_AdjList_Append(&self->adj_list[w], (c_uint_t)edge_id);
|
|
if (err != C_SUCCESS) return err;
|
|
|
|
self->E++;
|
|
return C_SUCCESS;
|
|
}
|
|
|
|
c_err_t c_EdgeWeightedGraph_GetEdge(c_EdgeWeightedGraph_t* self, c_size_t edge_idx, c_Edge_t* edge) {
|
|
if (!self ) return C_ERR_PARAM;
|
|
|
|
/* Strict firewall boundary validation against the total allocated edge count */
|
|
if (edge_idx >= self->E) return C_ERR_OUTOFBOUND;
|
|
|
|
/* Execute a fast bitwise block-copy of the edge object contents */
|
|
if (edge) {
|
|
*edge = self->edges_pool[edge_idx];
|
|
}
|
|
|
|
return C_SUCCESS;
|
|
}
|
|
|
|
|
|
c_err_t c_EdgeWeightedGraph_RemoveEdge(c_EdgeWeightedGraph_t* self, c_size_t edge_id) {
|
|
if (!self) return C_ERR_PARAM;
|
|
|
|
/* 1. Bounds check firewall validation */
|
|
if (edge_id >= self->E) return C_ERR_OUTOFBOUND;
|
|
|
|
c_Edge_t* edge = &self->edges_pool[edge_id];
|
|
|
|
/* If the edge is already soft-deleted, skip to prevent repetitive lookups */
|
|
if (edge->v == C_EDGE_SENTINEL) return C_SUCCESS;
|
|
|
|
c_size_t vertex_v = edge->v;
|
|
c_size_t vertex_w = edge->w;
|
|
|
|
/* 2. Purge the edge_id reference from vertex v's adjacency list */
|
|
c_UIntArray_t* adj_v = &self->adj_list[vertex_v];
|
|
c_size_t size_v = (c_size_t)c_UIntArray_GetSize(adj_v);
|
|
c_bool_t found_v = C_FALSE;
|
|
|
|
for (c_size_t i = 0; i < size_v; ++i) {
|
|
c_uint_t generic_id = 0;
|
|
if (c_UIntArray_Get(adj_v, i, &generic_id) == C_SUCCESS) {
|
|
if ((c_size_t)generic_id == edge_id) {
|
|
c_UIntArray_Remove(adj_v, i);
|
|
found_v = C_TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* 3. Purge the edge_id reference from vertex w's adjacency list */
|
|
c_UIntArray_t* adj_w = &self->adj_list[vertex_w];
|
|
c_size_t size_w = (c_size_t)c_UIntArray_GetSize(adj_w);
|
|
c_bool_t found_w = C_FALSE;
|
|
|
|
for (c_size_t i = 0; i < size_w; ++i) {
|
|
c_uint_t generic_id = 0;
|
|
if (c_UIntArray_Get(adj_w, i, &generic_id) == C_SUCCESS) {
|
|
if ((c_size_t)generic_id == edge_id) {
|
|
c_UIntArray_Remove(adj_w, i);
|
|
found_w = C_TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* 4. Finalize soft-deletion updates inside the pool slot */
|
|
if (found_v || found_w) {
|
|
edge->v = C_EDGE_SENTINEL;
|
|
edge->w = C_EDGE_SENTINEL;
|
|
edge->weight = 0.0;
|
|
} else {
|
|
return C_ERR_NOTFOUND;
|
|
}
|
|
|
|
return C_SUCCESS;
|
|
}
|
|
|
|
|