static uint32_t edge_hash_function(void* key)
{
struct edge* edge = key;
- /* This will always return the same value, even if the two endpoints are swapped. */
+ /* This will always return the same value for any given pair, even if the two endpoints
+ * are swapped. */
return standard_pointer_hash_function(edge->v1) ^ standard_pointer_hash_function(edge->v2);
}
g->edges.table.cmpfunction = edge_comparison_function;
}
-void graph_reset(struct graph* g)
+void graph_empty(struct graph* g)
{
lazy_init(g);
{
struct vertex* vertex = hashtable_pop(&g->vertices);
if (!vertex)
- return;
+ break;
set_reset(&vertex->edges);
free(vertex);
for (;;)
{
struct edge* edge = set_pop(&g->edges);
+ if (!edge)
+ break;
free(edge);
}
}
+void graph_reset(struct graph* g)
+{
+ graph_empty(g);
+}
+
bool graph_contains_vertex(struct graph* g, void* data)
{
lazy_init(g);
{
vertex = calloc(1, sizeof(struct vertex));
vertex->data = data;
+ vertex->edges.table.hashfunction = edge_hash_function;
+ vertex->edges.table.cmpfunction = edge_comparison_function;
hashtable_put(&g->vertices, data, vertex);
}
-
+
return vertex;
}
struct edge template;
struct edge* e;
+ if (data1 == data2)
+ return;
+
template.v1 = find_or_add_vertex(g, data1);
template.v2 = find_or_add_vertex(g, data2);
if (template.v1 == template.v2)
vertex = hashtable_get(&g->vertices, data);
if (!vertex)
return;
-
+
for (;;)
{
struct vertex* other;
free(vertex);
}
+void graph_merge_vertices(struct graph* g, void* master, void* slave)
+{
+ struct vertex* masterVertex;
+ struct vertex* slaveVertex;
+
+ lazy_init(g);
+ masterVertex = hashtable_get(&g->vertices, master);
+ slaveVertex = hashtable_get(&g->vertices, slave);
+
+ if (!masterVertex || !slaveVertex)
+ return;
+
+ for (;;)
+ {
+ struct vertex* v1;
+ struct vertex* v2;
+ struct edge* e = set_get_any(&slaveVertex->edges);
+ if (!e)
+ break;
+
+ v1 = e->v1;
+ v2 = e->v2;
+
+ if (v1 == slaveVertex)
+ graph_add_edge(g, master, v2->data);
+ if (v2 == slaveVertex)
+ graph_add_edge(g, master, v1->data);
+ graph_remove_edge(g, v1->data, v2->data);
+ }
+
+ assert(slaveVertex->degree == 0);
+ graph_remove_vertex(g, slave);
+}
+
int graph_get_vertex_degree(struct graph* g, void* data)
{
struct vertex* vertex;
return false;
}
}
+
+void* graph_next_neighbour(struct graph* g, void* origin, struct neighbour_iterator* it)
+{
+ struct edge* e;
+
+ lazy_init(g);
+ if (!it->vertex)
+ it->vertex = hashtable_get(&g->vertices, origin);
+ if (it->vertex)
+ {
+ e = set_next(&it->vertex->edges, &it->sit);
+ if (e)
+ {
+ if (e->v1 == it->vertex)
+ it->data = e->v2->data;
+ else
+ it->data = e->v1->data;
+ return it->data;
+ }
+ }
+
+ it->vertex = NULL;
+ it->data = NULL;
+ return it->data;
+}
struct set_iterator sit;
};
+struct neighbour_iterator
+{
+ /* Public */
+ void* data;
+
+ /* Private */
+ struct vertex* vertex;
+ struct set_iterator sit;
+};
+
+extern void graph_empty(struct graph* g);
extern void graph_reset(struct graph* g);
extern bool graph_contains_vertex(struct graph* g, void* data);
extern void graph_add_vertex(struct graph* g, void* data);
extern void graph_remove_vertex(struct graph* g, void* data);
+extern void graph_merge_vertices(struct graph* g, void* master, void* slave);
extern bool graph_contains_edge(struct graph* g, void* data1, void* data2);
extern void graph_add_edge(struct graph* g, void* data1, void* data2);
extern void graph_remove_edge(struct graph* g, void* data1, void* data2);
extern void* graph_next_vertex(struct graph* g, struct vertex_iterator* it);
extern bool graph_next_edge(struct graph* g, struct edge_iterator* it);
+extern void* graph_next_neighbour(struct graph* g, void* origin, struct neighbour_iterator* it);
#endif