1 // -*- mode:C++ -*- |
|
2 |
|
3 #ifndef LEMON_LIST_GRAPH_H |
|
4 #define LEMON_LIST_GRAPH_H |
|
5 |
|
6 ///\ingroup graphs |
|
7 ///\file |
|
8 ///\brief ListGraph, SymListGraph, NodeSet and EdgeSet classes. |
|
9 |
|
10 #include <vector> |
|
11 #include <climits> |
|
12 |
|
13 #include "invalid.h" |
|
14 |
|
15 #include "array_map_factory.h" |
|
16 #include "map_registry.h" |
|
17 |
|
18 #include "map_defines.h" |
|
19 |
|
20 namespace lemon { |
|
21 |
|
22 /// \addtogroup graphs |
|
23 /// @{ |
|
24 |
|
25 ///A list graph class. |
|
26 |
|
27 ///This is a simple and fast erasable graph implementation. |
|
28 /// |
|
29 ///It conforms to the graph interface documented under |
|
30 ///the description of \ref Graph. |
|
31 ///\sa \ref Graph. |
|
32 class ListGraph { |
|
33 |
|
34 //Nodes are double linked. |
|
35 //The free nodes are only single linked using the "next" field. |
|
36 struct NodeT |
|
37 { |
|
38 int first_in,first_out; |
|
39 int prev, next; |
|
40 // NodeT() {} |
|
41 }; |
|
42 //Edges are double linked. |
|
43 //The free edges are only single linked using the "next_in" field. |
|
44 struct EdgeT |
|
45 { |
|
46 int target, source; |
|
47 int prev_in, prev_out; |
|
48 int next_in, next_out; |
|
49 //FIXME: is this necessary? |
|
50 // EdgeT() : next_in(-1), next_out(-1) prev_in(-1), prev_out(-1) {} |
|
51 }; |
|
52 |
|
53 std::vector<NodeT> nodes; |
|
54 //The first node |
|
55 int first_node; |
|
56 //The first free node |
|
57 int first_free_node; |
|
58 std::vector<EdgeT> edges; |
|
59 //The first free edge |
|
60 int first_free_edge; |
|
61 |
|
62 protected: |
|
63 |
|
64 public: |
|
65 |
|
66 class Node; |
|
67 class Edge; |
|
68 |
|
69 typedef ListGraph Graph; |
|
70 |
|
71 public: |
|
72 |
|
73 class NodeIt; |
|
74 class EdgeIt; |
|
75 class OutEdgeIt; |
|
76 class InEdgeIt; |
|
77 |
|
78 CREATE_MAP_REGISTRIES; |
|
79 CREATE_MAPS(ArrayMapFactory); |
|
80 public: |
|
81 |
|
82 ListGraph() : nodes(), first_node(-1), |
|
83 first_free_node(-1), edges(), first_free_edge(-1) {} |
|
84 ListGraph(const ListGraph &_g) : nodes(_g.nodes), first_node(_g.first_node), |
|
85 first_free_node(_g.first_free_node), |
|
86 edges(_g.edges), |
|
87 first_free_edge(_g.first_free_edge) {} |
|
88 |
|
89 |
|
90 int nodeNum() const { return nodes.size(); } //FIXME: What is this? |
|
91 int edgeNum() const { return edges.size(); } //FIXME: What is this? |
|
92 |
|
93 ///Set the expected number of edges |
|
94 |
|
95 ///With this function, it is possible to set the expected number of edges. |
|
96 ///The use of this fasten the building of the graph and makes |
|
97 ///it possible to avoid the superfluous memory allocation. |
|
98 void reserveEdge(int n) { edges.reserve(n); }; |
|
99 |
|
100 ///\bug This function does something different than |
|
101 ///its name would suggests... |
|
102 int maxNodeId() const { return nodes.size(); } //FIXME: What is this? |
|
103 ///\bug This function does something different than |
|
104 ///its name would suggests... |
|
105 int maxEdgeId() const { return edges.size(); } //FIXME: What is this? |
|
106 |
|
107 Node source(Edge e) const { return edges[e.n].source; } |
|
108 Node target(Edge e) const { return edges[e.n].target; } |
|
109 |
|
110 Node aNode(OutEdgeIt e) const { return edges[e.n].source; } |
|
111 Node aNode(InEdgeIt e) const { return edges[e.n].target; } |
|
112 |
|
113 Node bNode(OutEdgeIt e) const { return edges[e.n].target; } |
|
114 Node bNode(InEdgeIt e) const { return edges[e.n].source; } |
|
115 |
|
116 NodeIt& first(NodeIt& v) const { |
|
117 v=NodeIt(*this); return v; } |
|
118 EdgeIt& first(EdgeIt& e) const { |
|
119 e=EdgeIt(*this); return e; } |
|
120 OutEdgeIt& first(OutEdgeIt& e, const Node v) const { |
|
121 e=OutEdgeIt(*this,v); return e; } |
|
122 InEdgeIt& first(InEdgeIt& e, const Node v) const { |
|
123 e=InEdgeIt(*this,v); return e; } |
|
124 |
|
125 // template< typename It > |
|
126 // It first() const { It e; first(e); return e; } |
|
127 |
|
128 // template< typename It > |
|
129 // It first(Node v) const { It e; first(e,v); return e; } |
|
130 |
|
131 bool valid(Edge e) const { return e.n!=-1; } |
|
132 bool valid(Node n) const { return n.n!=-1; } |
|
133 |
|
134 void setInvalid(Edge &e) { e.n=-1; } |
|
135 void setInvalid(Node &n) { n.n=-1; } |
|
136 |
|
137 template <typename It> It getNext(It it) const |
|
138 { It tmp(it); return next(tmp); } |
|
139 |
|
140 NodeIt& next(NodeIt& it) const { |
|
141 it.n=nodes[it.n].next; |
|
142 return it; |
|
143 } |
|
144 OutEdgeIt& next(OutEdgeIt& it) const |
|
145 { it.n=edges[it.n].next_out; return it; } |
|
146 InEdgeIt& next(InEdgeIt& it) const |
|
147 { it.n=edges[it.n].next_in; return it; } |
|
148 EdgeIt& next(EdgeIt& it) const { |
|
149 if(edges[it.n].next_in!=-1) { |
|
150 it.n=edges[it.n].next_in; |
|
151 } |
|
152 else { |
|
153 int n; |
|
154 for(n=nodes[edges[it.n].target].next; |
|
155 n!=-1 && nodes[n].first_in == -1; |
|
156 n = nodes[n].next) ; |
|
157 it.n = (n==-1)?-1:nodes[n].first_in; |
|
158 } |
|
159 return it; |
|
160 } |
|
161 |
|
162 int id(Node v) const { return v.n; } |
|
163 int id(Edge e) const { return e.n; } |
|
164 |
|
165 /// Adds a new node to the graph. |
|
166 |
|
167 /// \todo It adds the nodes in a reversed order. |
|
168 /// (i.e. the lastly added node becomes the first.) |
|
169 Node addNode() { |
|
170 int n; |
|
171 |
|
172 if(first_free_node==-1) |
|
173 { |
|
174 n = nodes.size(); |
|
175 nodes.push_back(NodeT()); |
|
176 } |
|
177 else { |
|
178 n = first_free_node; |
|
179 first_free_node = nodes[n].next; |
|
180 } |
|
181 |
|
182 nodes[n].next = first_node; |
|
183 if(first_node != -1) nodes[first_node].prev = n; |
|
184 first_node = n; |
|
185 nodes[n].prev = -1; |
|
186 |
|
187 nodes[n].first_in = nodes[n].first_out = -1; |
|
188 |
|
189 Node nn; nn.n=n; |
|
190 |
|
191 //Update dynamic maps |
|
192 node_maps.add(nn); |
|
193 |
|
194 return nn; |
|
195 } |
|
196 |
|
197 Edge addEdge(Node u, Node v) { |
|
198 int n; |
|
199 |
|
200 if(first_free_edge==-1) |
|
201 { |
|
202 n = edges.size(); |
|
203 edges.push_back(EdgeT()); |
|
204 } |
|
205 else { |
|
206 n = first_free_edge; |
|
207 first_free_edge = edges[n].next_in; |
|
208 } |
|
209 |
|
210 edges[n].source = u.n; edges[n].target = v.n; |
|
211 |
|
212 edges[n].next_out = nodes[u.n].first_out; |
|
213 if(nodes[u.n].first_out != -1) edges[nodes[u.n].first_out].prev_out = n; |
|
214 edges[n].next_in = nodes[v.n].first_in; |
|
215 if(nodes[v.n].first_in != -1) edges[nodes[v.n].first_in].prev_in = n; |
|
216 edges[n].prev_in = edges[n].prev_out = -1; |
|
217 |
|
218 nodes[u.n].first_out = nodes[v.n].first_in = n; |
|
219 |
|
220 Edge e; e.n=n; |
|
221 |
|
222 //Update dynamic maps |
|
223 edge_maps.add(e); |
|
224 |
|
225 return e; |
|
226 } |
|
227 |
|
228 private: |
|
229 void eraseEdge(int n) { |
|
230 |
|
231 if(edges[n].next_in!=-1) |
|
232 edges[edges[n].next_in].prev_in = edges[n].prev_in; |
|
233 if(edges[n].prev_in!=-1) |
|
234 edges[edges[n].prev_in].next_in = edges[n].next_in; |
|
235 else nodes[edges[n].target].first_in = edges[n].next_in; |
|
236 |
|
237 if(edges[n].next_out!=-1) |
|
238 edges[edges[n].next_out].prev_out = edges[n].prev_out; |
|
239 if(edges[n].prev_out!=-1) |
|
240 edges[edges[n].prev_out].next_out = edges[n].next_out; |
|
241 else nodes[edges[n].source].first_out = edges[n].next_out; |
|
242 |
|
243 edges[n].next_in = first_free_edge; |
|
244 first_free_edge = n; |
|
245 |
|
246 //Update dynamic maps |
|
247 Edge e; e.n=n; |
|
248 } |
|
249 |
|
250 public: |
|
251 |
|
252 void erase(Node nn) { |
|
253 int n=nn.n; |
|
254 |
|
255 int m; |
|
256 while((m=nodes[n].first_in)!=-1) eraseEdge(m); |
|
257 while((m=nodes[n].first_out)!=-1) eraseEdge(m); |
|
258 |
|
259 if(nodes[n].next != -1) nodes[nodes[n].next].prev = nodes[n].prev; |
|
260 if(nodes[n].prev != -1) nodes[nodes[n].prev].next = nodes[n].next; |
|
261 else first_node = nodes[n].next; |
|
262 |
|
263 nodes[n].next = first_free_node; |
|
264 first_free_node = n; |
|
265 |
|
266 //Update dynamic maps |
|
267 node_maps.erase(nn); |
|
268 } |
|
269 |
|
270 void erase(Edge e) { |
|
271 edge_maps.erase(e); |
|
272 eraseEdge(e.n); |
|
273 } |
|
274 |
|
275 ///\bug Dynamic maps must be updated! |
|
276 /// |
|
277 void clear() { |
|
278 nodes.clear();edges.clear(); |
|
279 first_node=first_free_node=first_free_edge=-1; |
|
280 } |
|
281 |
|
282 class Node { |
|
283 friend class ListGraph; |
|
284 template <typename T> friend class NodeMap; |
|
285 |
|
286 friend class Edge; |
|
287 friend class OutEdgeIt; |
|
288 friend class InEdgeIt; |
|
289 friend class SymEdge; |
|
290 |
|
291 protected: |
|
292 int n; |
|
293 friend int ListGraph::id(Node v) const; |
|
294 Node(int nn) {n=nn;} |
|
295 public: |
|
296 Node() {} |
|
297 Node (Invalid) { n=-1; } |
|
298 bool operator==(const Node i) const {return n==i.n;} |
|
299 bool operator!=(const Node i) const {return n!=i.n;} |
|
300 bool operator<(const Node i) const {return n<i.n;} |
|
301 }; |
|
302 |
|
303 class NodeIt : public Node { |
|
304 friend class ListGraph; |
|
305 public: |
|
306 NodeIt() : Node() { } |
|
307 NodeIt(Invalid i) : Node(i) { } |
|
308 NodeIt(const ListGraph& G) : Node(G.first_node) { } |
|
309 ///\todo Undocumented conversion Node -\> NodeIt. |
|
310 NodeIt(const ListGraph& G, const Node &n) : Node(n) { } |
|
311 }; |
|
312 |
|
313 class Edge { |
|
314 friend class ListGraph; |
|
315 template <typename T> friend class EdgeMap; |
|
316 |
|
317 //template <typename T> friend class SymListGraph::SymEdgeMap; |
|
318 //friend Edge SymListGraph::opposite(Edge) const; |
|
319 |
|
320 friend class Node; |
|
321 friend class NodeIt; |
|
322 protected: |
|
323 int n; |
|
324 friend int ListGraph::id(Edge e) const; |
|
325 |
|
326 Edge(int nn) {n=nn;} |
|
327 public: |
|
328 Edge() { } |
|
329 Edge (Invalid) { n=-1; } |
|
330 bool operator==(const Edge i) const {return n==i.n;} |
|
331 bool operator!=(const Edge i) const {return n!=i.n;} |
|
332 bool operator<(const Edge i) const {return n<i.n;} |
|
333 ///\bug This is a workaround until somebody tells me how to |
|
334 ///make class \c SymListGraph::SymEdgeMap friend of Edge |
|
335 int &idref() {return n;} |
|
336 const int &idref() const {return n;} |
|
337 }; |
|
338 |
|
339 class EdgeIt : public Edge { |
|
340 friend class ListGraph; |
|
341 public: |
|
342 EdgeIt(const ListGraph& G) : Edge() { |
|
343 int m; |
|
344 for(m=G.first_node; |
|
345 m!=-1 && G.nodes[m].first_in == -1; m = G.nodes[m].next); |
|
346 n = (m==-1)?-1:G.nodes[m].first_in; |
|
347 } |
|
348 EdgeIt (Invalid i) : Edge(i) { } |
|
349 EdgeIt() : Edge() { } |
|
350 ///\bug This is a workaround until somebody tells me how to |
|
351 ///make class \c SymListGraph::SymEdgeMap friend of Edge |
|
352 int &idref() {return n;} |
|
353 }; |
|
354 |
|
355 class OutEdgeIt : public Edge { |
|
356 friend class ListGraph; |
|
357 public: |
|
358 OutEdgeIt() : Edge() { } |
|
359 OutEdgeIt (Invalid i) : Edge(i) { } |
|
360 |
|
361 OutEdgeIt(const ListGraph& G,const Node v) |
|
362 : Edge(G.nodes[v.n].first_out) {} |
|
363 }; |
|
364 |
|
365 class InEdgeIt : public Edge { |
|
366 friend class ListGraph; |
|
367 public: |
|
368 InEdgeIt() : Edge() { } |
|
369 InEdgeIt (Invalid i) : Edge(i) { } |
|
370 InEdgeIt(const ListGraph& G,Node v) :Edge(G.nodes[v.n].first_in) {} |
|
371 }; |
|
372 |
|
373 }; |
|
374 |
|
375 ///Graph for bidirectional edges. |
|
376 |
|
377 ///The purpose of this graph structure is to handle graphs |
|
378 ///having bidirectional edges. Here the function \c addEdge(u,v) adds a pair |
|
379 ///of oppositely directed edges. |
|
380 ///There is a new edge map type called |
|
381 ///\ref SymListGraph::SymEdgeMap "SymEdgeMap" |
|
382 ///that complements this |
|
383 ///feature by |
|
384 ///storing shared values for the edge pairs. The usual |
|
385 ///\ref Graph::EdgeMap "EdgeMap" |
|
386 ///can be used |
|
387 ///as well. |
|
388 /// |
|
389 ///The oppositely directed edge can also be obtained easily |
|
390 ///using \ref opposite. |
|
391 /// |
|
392 ///Here erase(Edge) deletes a pair of edges. |
|
393 /// |
|
394 ///\todo this date structure need some reconsiderations. Maybe it |
|
395 ///should be implemented independently from ListGraph. |
|
396 |
|
397 } |
|
398 |
|
399 #endif //LEMON_LIST_GRAPH_H |
|