]> git.puffer.fish Git - matthieu/frr.git/commitdiff
lib: Add edge removal to graph data structure
authorQuentin Young <qlyoung@cumulusnetworks.com>
Sun, 18 Sep 2016 20:31:20 +0000 (20:31 +0000)
committerQuentin Young <qlyoung@cumulusnetworks.com>
Sun, 18 Sep 2016 20:31:20 +0000 (20:31 +0000)
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>
lib/graph.c
lib/graph.h

index 18f32b8ca2a051973953aa50a53990c0f4339c09..7c59fe95b524e53b29da15a23164185e5f5917a6 100644 (file)
@@ -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)
 {
index b6a03b938aac19dcf867b9cd532f2d0c09b1c07a..8d8aa3823ba5f90474b2732449eda127ce22c1bd 100644 (file)
@@ -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