/*
This software may only be used by you under license from AT&T Corp.
("AT&T"). A copy of AT&T's Source Code Agreement is available at
AT&T's Internet website having the URL:
<http://www.research.att.com/sw/tools/graphviz/license/source.html>
If you received this software without first entering into a license
with AT&T, you have an infringing copy of this software and cannot use
it without violating AT&T's intellectual property rights.
*/
#pragma prototyped
/*
* Decompose finds the connected components of a graph.
* It searches the temporary edges and ignores non-root nodes.
* The roots of the search are the real nodes of the graph,
* but any virtual nodes discovered are also included in the
* component.
*/
#include "dot.h"
static graph_t *G;
static node_t *Last_node;
static char Cmark;
void begin_component(void)
{
Last_node = GD_nlist(G) = NULL;
}
void add_to_component(node_t* n)
{
GD_n_nodes(G)++;
ND_mark(n) = Cmark;
if (Last_node) {
ND_prev(n) = Last_node;
ND_next(Last_node) = n;
}
else {
ND_prev(n) = NULL;
GD_nlist(G) = n;
}
Last_node = n;
ND_next(n) = NULL;
}
void end_component(void)
{
int i;
i = GD_comp(G).size++;
GD_comp(G).list = ALLOC(GD_comp(G).size,GD_comp(G).list,node_t*);
GD_comp(G).list[i] = GD_nlist(G);
}
void search_component(graph_t* g, node_t* n)
{
int c,i;
elist vec[4];
node_t *other;
edge_t *e;
add_to_component(n);
vec[0] = ND_out(n); vec[1] = ND_in(n);
vec[2] = ND_flat_out(n); vec[3] = ND_flat_in(n);
for (c = 0; c <= 3; c++) {
if (vec[c].list) for (i = 0; (e = vec[c].list[i]); i++) {
if ((other = e->head) == n) other = e->tail;
if ((ND_mark(other) != Cmark) && (other == UF_find(other)))
search_component(g,other);
}
}
}
void decompose(graph_t* g, int pass)
{
graph_t *subg;
node_t *n,*v;
G = g;
if (++Cmark == 0) Cmark = 1;
GD_n_nodes(g) = GD_comp(g).size = 0;
for (n = agfstnode(g); n; n = agnxtnode(g,n)) {
v = n;
if ((pass > 0) && (subg = ND_clust(v)))
v = GD_rankleader(subg)[ND_rank(v)];
else if (v != UF_find(v)) continue;
if (ND_mark(v) != Cmark) {
begin_component();
search_component(g,v);
end_component();
}
}
}
|