forked from Mirror/frr
lib: Add edge removal to graph data structure
Ability to remove directed edge between two nodes. Also ensures that adjacency vectors have no null entries. Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
This commit is contained in:
parent
535ef5569a
commit
ba06a3a0de
51
lib/graph.c
51
lib/graph.c
|
@ -50,6 +50,16 @@ graph_new_node (struct graph *graph, void *data, void (*del) (void*))
|
|||
return node;
|
||||
}
|
||||
|
||||
static void
|
||||
vector_remove (vector v, unsigned int ix)
|
||||
{
|
||||
vector_unset (v, ix);
|
||||
if (ix == vector_active (v)) return;
|
||||
for (; ix < vector_active (v) - 1; ix++)
|
||||
v->index[ix] = v->index[ix+1];
|
||||
v->active--;
|
||||
}
|
||||
|
||||
void
|
||||
graph_delete_node (struct graph *graph, struct graph_node *node)
|
||||
{
|
||||
|
@ -58,25 +68,23 @@ graph_delete_node (struct graph *graph, struct graph_node *node)
|
|||
// an adjacent node
|
||||
struct graph_node *adj;
|
||||
|
||||
// for all nodes that have an edge to us, remove us from their ->to
|
||||
for (unsigned int i = 0; i < vector_active (node->from); i++)
|
||||
// remove all edges from other nodes to us
|
||||
vector edges = vector_copy (node->from);
|
||||
for (unsigned int i = 0; i < vector_active (edges); i++)
|
||||
{
|
||||
adj = vector_slot (node->from, i);
|
||||
if (!adj) continue;
|
||||
for (unsigned int j = 0; j < vector_active (adj->to); j++)
|
||||
if (vector_slot (adj->to, j) == node)
|
||||
vector_unset (adj->to, j);
|
||||
adj = vector_slot (edges, i);
|
||||
graph_remove_edge (adj, node);
|
||||
}
|
||||
vector_free (edges);
|
||||
|
||||
// for all nodes that we have an edge to, remove us from their ->from
|
||||
for (unsigned int i = 0; i < vector_active (node->to); i++)
|
||||
// remove all edges from us to other nodes
|
||||
edges = vector_copy (node->to);
|
||||
for (unsigned int i = 0; i < vector_active (edges); i++)
|
||||
{
|
||||
adj = vector_slot (node->to, i);
|
||||
if (!adj) continue;
|
||||
for (unsigned int j = 0; j < vector_active (adj->from); j++)
|
||||
if (vector_slot (adj->from, j) == node)
|
||||
vector_unset (adj->from, j);
|
||||
adj = vector_slot (edges, i);
|
||||
graph_remove_edge (node, adj);
|
||||
}
|
||||
vector_free (edges);
|
||||
|
||||
// if there is a deletion callback, call it
|
||||
if (node->del && node->data)
|
||||
|
@ -89,7 +97,7 @@ graph_delete_node (struct graph *graph, struct graph_node *node)
|
|||
// remove node from graph->nodes
|
||||
for (unsigned int i = 0; i < vector_active (graph->nodes); i++)
|
||||
if (vector_slot (graph->nodes, i) == node)
|
||||
vector_unset (graph->nodes, i);
|
||||
vector_remove (graph->nodes, i);
|
||||
|
||||
// free the node itself
|
||||
XFREE (MTYPE_GRAPH_NODE, node);
|
||||
|
@ -103,6 +111,19 @@ graph_add_edge (struct graph_node *from, struct graph_node *to)
|
|||
return to;
|
||||
}
|
||||
|
||||
void
|
||||
graph_remove_edge (struct graph_node *from, struct graph_node *to)
|
||||
{
|
||||
// remove from from to->from
|
||||
for (unsigned int i = 0; i < vector_active (to->from); i++)
|
||||
if (vector_slot (to->from, i) == from)
|
||||
vector_remove (to->from, i);
|
||||
// remove to from from->to
|
||||
for (unsigned int i = 0; i < vector_active (from->to); i++)
|
||||
if (vector_slot (from->to, i) == to)
|
||||
vector_remove (from->to, i);
|
||||
}
|
||||
|
||||
void
|
||||
graph_delete_graph (struct graph *graph)
|
||||
{
|
||||
|
|
11
lib/graph.h
11
lib/graph.h
|
@ -64,6 +64,7 @@ graph_new_node (struct graph *graph, void *data, void (*del) (void*));
|
|||
* If *data and *del are non-null, the following call is made:
|
||||
* (*node->del) (node->data);
|
||||
*
|
||||
* @param[in] graph the graph this node belongs to
|
||||
* @param[out] node pointer to node to delete
|
||||
*/
|
||||
void
|
||||
|
@ -80,8 +81,16 @@ struct graph_node *
|
|||
graph_add_edge (struct graph_node *from, struct graph_node *to);
|
||||
|
||||
/**
|
||||
* Deletes a graph.
|
||||
* Removes a directed edge between two nodes.
|
||||
*
|
||||
* @param[in] from
|
||||
* @param[in] to
|
||||
*/
|
||||
void
|
||||
graph_remove_edge (struct graph_node *from, struct graph_node *to);
|
||||
|
||||
/**
|
||||
* Deletes a graph.
|
||||
* Calls graph_delete_node on each node before freeing the graph struct itself.
|
||||
*
|
||||
* @param graph the graph to delete
|
||||
|
|
Loading…
Reference in a new issue