GRASS Programmer's Manual  6.5.svn(2014)-r66266
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
components.c
Go to the documentation of this file.
1 
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <grass/gis.h>
19 #include <grass/Vect.h>
20 #include <grass/glocale.h>
21 #include <grass/dgl/graph.h>
22 
32 int NetA_weakly_connected_components(dglGraph_s * graph, int *component)
33 {
34  int nnodes;
35  dglInt32_t *stack;
36  int *visited;
37  int stack_size, components;
38  dglInt32_t *cur_node;
40 
41  components = 0;
42  nnodes = dglGet_NodeCount(graph);
43  stack = (dglInt32_t *) G_calloc(nnodes + 1, sizeof(dglInt32_t));
44  visited = (int *)G_calloc(nnodes + 1, sizeof(int));
45  if (!stack || !visited) {
46  G_fatal_error(_("Out of memory"));
47  return -1;
48  }
49 
50  dglNode_T_Initialize(&nt, graph);
51 
52  for (cur_node = dglNode_T_First(&nt); cur_node;
53  cur_node = dglNode_T_Next(&nt)) {
54  dglInt32_t node_id = dglNodeGet_Id(graph, cur_node);
55 
56  if (!visited[node_id]) {
57  visited[node_id] = 1;
58  stack[0] = node_id;
59  stack_size = 1;
60  component[node_id] = ++components;
61  while (stack_size) {
62  dglInt32_t *node, *edgeset, *edge;
64 
65  node = dglGetNode(graph, stack[--stack_size]);
66  edgeset = dglNodeGet_OutEdgeset(graph, node);
67  dglEdgeset_T_Initialize(&et, graph, edgeset);
68  for (edge = dglEdgeset_T_First(&et); edge;
69  edge = dglEdgeset_T_Next(&et)) {
70  dglInt32_t to;
71 
72  to = dglNodeGet_Id(graph, dglEdgeGet_Tail(graph, edge));
73  if (!visited[to]) {
74  visited[to] = 1;
75  component[to] = components;
76  stack[stack_size++] = to;
77  }
78  }
80  }
81  }
82  }
83  dglNode_T_Release(&nt);
84  G_free(visited);
85  return components;
86 }
87 
97 int NetA_strongly_connected_components(dglGraph_s * graph, int *component)
98 {
99  int nnodes;
100  dglInt32_t *stack, *order;
101  int *visited, *processed;
102  int stack_size, order_size, components;
103  dglInt32_t *node;
105 
106  components = 0;
107  nnodes = dglGet_NodeCount(graph);
108  stack = (dglInt32_t *) G_calloc(nnodes + 1, sizeof(dglInt32_t));
109  order = (dglInt32_t *) G_calloc(nnodes + 1, sizeof(dglInt32_t));
110  visited = (int *)G_calloc(nnodes + 1, sizeof(int));
111  processed = (int *)G_calloc(nnodes + 1, sizeof(int));
112  if (!stack || !visited || !order || !processed) {
113  G_fatal_error(_("Out of memory"));
114  return -1;
115  }
116 
117  order_size = 0;
118  dglNode_T_Initialize(&nt, graph);
119 
120  for (node = dglNode_T_First(&nt); node; node = dglNode_T_Next(&nt)) {
121  dglInt32_t node_id = dglNodeGet_Id(graph, node);
122 
123  component[node_id] = 0;
124  if (!visited[node_id]) {
125  visited[node_id] = 1;
126  stack[0] = node_id;
127  stack_size = 1;
128  while (stack_size) {
129  dglInt32_t *node, *edgeset, *edge;
131  dglInt32_t cur_node_id = stack[stack_size - 1];
132 
133  if (processed[cur_node_id]) {
134  stack_size--;
135  order[order_size++] = cur_node_id;
136  continue;
137  }
138  processed[cur_node_id] = 1;
139  node = dglGetNode(graph, cur_node_id);
140  edgeset = dglNodeGet_OutEdgeset(graph, node);
141  dglEdgeset_T_Initialize(&et, graph, edgeset);
142  for (edge = dglEdgeset_T_First(&et); edge;
143  edge = dglEdgeset_T_Next(&et)) {
144  dglInt32_t to;
145 
146  if (dglEdgeGet_Id(graph, edge) < 0)
147  continue; /*ignore backward edges */
148  to = dglNodeGet_Id(graph, dglEdgeGet_Tail(graph, edge));
149  if (!visited[to]) {
150  visited[to] = 1;
151  stack[stack_size++] = to;
152  }
153  }
155  }
156  }
157  }
158 
159  dglNode_T_Release(&nt);
160 
161  while (order_size) {
162  dglInt32_t node_id = order[--order_size];
163 
164  if (component[node_id])
165  continue;
166  components++;
167  component[node_id] = components;
168  stack[0] = node_id;
169  stack_size = 1;
170  while (stack_size) {
171  dglInt32_t *node, *edgeset, *edge;
173  dglInt32_t cur_node_id = stack[--stack_size];
174 
175  node = dglGetNode(graph, cur_node_id);
176  edgeset = dglNodeGet_OutEdgeset(graph, node);
177  dglEdgeset_T_Initialize(&et, graph, edgeset);
178  for (edge = dglEdgeset_T_First(&et); edge;
179  edge = dglEdgeset_T_Next(&et)) {
180  dglInt32_t to;
181 
182  if (dglEdgeGet_Id(graph, edge) > 0)
183  continue; /*ignore forward edges */
184  to = dglNodeGet_Id(graph, dglEdgeGet_Tail(graph, edge));
185  if (!component[to]) {
186  component[to] = components;
187  stack[stack_size++] = to;
188  }
189  }
191  }
192  }
193 
194  G_free(stack);
195  G_free(visited);
196  G_free(order);
197  G_free(processed);
198  return components;
199 }
dglInt32_t * dglEdgeGet_Tail(dglGraph_s *pGraph, dglInt32_t *pnEdge)
Definition: dglib/graph.c:494
dglInt32_t dglNodeGet_Id(dglGraph_s *pGraph, dglInt32_t *pnNode)
Definition: dglib/graph.c:213
void G_free(void *buf)
Free allocated memory.
Definition: gis/alloc.c:142
int NetA_weakly_connected_components(dglGraph_s *graph, int *component)
Computes weekly connected components.
Definition: components.c:32
int NetA_strongly_connected_components(dglGraph_s *graph, int *component)
Computes strongly connected components.
Definition: components.c:97
int dglEdgeset_T_Initialize(dglEdgesetTraverser_s *pT, dglGraph_s *pGraph, dglInt32_t *pnEdgeset)
Definition: dglib/graph.c:1499
int dglNode_T_Initialize(dglNodeTraverser_s *pT, dglGraph_s *pGraph)
Definition: dglib/graph.c:1356
void dglNode_T_Release(dglNodeTraverser_s *pT)
Definition: dglib/graph.c:1371
dglInt32_t dglEdgeGet_Id(dglGraph_s *pGraph, dglInt32_t *pnEdge)
Definition: dglib/graph.c:438
void dglEdgeset_T_Release(dglEdgesetTraverser_s *pT)
Definition: dglib/graph.c:1515
dglInt32_t * dglEdgeset_T_First(dglEdgesetTraverser_s *pT)
Definition: dglib/graph.c:1519
dglInt32_t * dglGetNode(dglGraph_s *pGraph, dglInt32_t nNodeId)
Definition: dglib/graph.c:155
long dglInt32_t
Definition: type.h:37
dglInt32_t * dglNode_T_First(dglNodeTraverser_s *pT)
Definition: dglib/graph.c:1387
dglInt32_t * dglNodeGet_OutEdgeset(dglGraph_s *pGraph, dglInt32_t *pnNode)
Definition: dglib/graph.c:170
int dglGet_NodeCount(dglGraph_s *pgraph)
Definition: dglib/graph.c:1241
int G_fatal_error(const char *msg,...)
Print a fatal error message to stderr.
dglInt32_t * dglNode_T_Next(dglNodeTraverser_s *pT)
Definition: dglib/graph.c:1402
dglInt32_t * dglEdgeset_T_Next(dglEdgesetTraverser_s *pT)
Definition: dglib/graph.c:1534