2 |
2 |
3 #ifndef HUGO_SMART_GRAPH_H |
3 #ifndef HUGO_SMART_GRAPH_H |
4 #define HUGO_SMART_GRAPH_H |
4 #define HUGO_SMART_GRAPH_H |
5 |
5 |
6 ///\file |
6 ///\file |
7 ///\brief SmartGraph and SymSmartGraph classes. |
7 ///\brief ListGraph and SymListGraph classes. |
8 |
8 |
9 #include <vector> |
9 #include <vector> |
10 #include <limits.h> |
10 #include <limits.h> |
11 |
11 |
12 #include "invalid.h" |
12 #include "invalid.h" |
13 |
13 |
14 namespace hugo { |
14 namespace hugo { |
15 |
15 |
16 class SymSmartGraph; |
16 class SymListGraph; |
17 |
17 |
18 ///A smart graph class. |
18 ///A smart graph class. |
19 |
19 |
20 ///This is a simple and fast graph implementation. |
20 ///This is a simple and fast erasable graph implementation. |
21 ///It is also quite memory efficient, but at the price |
21 /// |
22 ///that <b> it does not support node and edge deletion</b>. |
|
23 ///It conforms to the graph interface documented under |
22 ///It conforms to the graph interface documented under |
24 ///the description of \ref GraphSkeleton. |
23 ///the description of \ref GraphSkeleton. |
25 ///\sa \ref GraphSkeleton. |
24 ///\sa \ref GraphSkeleton. |
26 class SmartGraph { |
25 class ListGraph { |
27 |
26 |
|
27 //Nodes are double linked. |
|
28 //The free nodes are only single linked using the "next" field. |
28 struct NodeT |
29 struct NodeT |
29 { |
30 { |
30 int first_in,first_out; |
31 int first_in,first_out; |
31 NodeT() : first_in(-1), first_out(-1) {} |
32 int prev, next; |
32 }; |
33 // NodeT() {} |
|
34 }; |
|
35 //Edges are double linked. |
|
36 //The free edges are only single linked using the "next_in" field. |
33 struct EdgeT |
37 struct EdgeT |
34 { |
38 { |
35 int head, tail, next_in, next_out; |
39 int head, tail; |
|
40 int prev_in, prev_out; |
|
41 int next_in, next_out; |
36 //FIXME: is this necessary? |
42 //FIXME: is this necessary? |
37 EdgeT() : next_in(-1), next_out(-1) {} |
43 // EdgeT() : next_in(-1), next_out(-1) prev_in(-1), prev_out(-1) {} |
38 }; |
44 }; |
39 |
45 |
40 std::vector<NodeT> nodes; |
46 std::vector<NodeT> nodes; |
41 |
47 //The first node |
|
48 int first_node; |
|
49 //The first free node |
|
50 int first_free_node; |
42 std::vector<EdgeT> edges; |
51 std::vector<EdgeT> edges; |
43 |
52 //The first free edge |
|
53 int first_free_edge; |
|
54 |
|
55 protected: |
|
56 |
|
57 template <typename Key> class DynMapBase |
|
58 { |
44 protected: |
59 protected: |
45 |
60 const ListGraph* G; |
46 template <typename Key> class DynMapBase |
|
47 { |
|
48 protected: |
|
49 const SmartGraph* G; |
|
50 public: |
61 public: |
51 virtual void add(const Key k) = NULL; |
62 virtual void add(const Key k) = NULL; |
52 virtual void erase(const Key k) = NULL; |
63 virtual void erase(const Key k) = NULL; |
53 DynMapBase(const SmartGraph &_G) : G(&_G) {} |
64 DynMapBase(const ListGraph &_G) : G(&_G) {} |
54 virtual ~DynMapBase() {} |
65 virtual ~DynMapBase() {} |
55 friend class SmartGraph; |
66 friend class ListGraph; |
56 }; |
67 }; |
57 |
68 |
58 public: |
69 public: |
59 template <typename T> class EdgeMap; |
70 template <typename T> class EdgeMap; |
60 template <typename T> class EdgeMap; |
71 template <typename T> class EdgeMap; |
61 |
72 |
62 class Node; |
73 class Node; |
63 class Edge; |
74 class Edge; |
64 |
75 |
65 // protected: |
76 // protected: |
66 // HELPME: |
77 // HELPME: |
137 |
152 |
138 template <typename It> It getNext(It it) const |
153 template <typename It> It getNext(It it) const |
139 { It tmp(it); return next(tmp); } |
154 { It tmp(it); return next(tmp); } |
140 |
155 |
141 NodeIt& next(NodeIt& it) const { |
156 NodeIt& next(NodeIt& it) const { |
142 it.n=(it.n+2)%(nodes.size()+1)-1; |
157 it.n=nodes[it.n].next; |
143 return it; |
158 return it; |
144 } |
159 } |
145 OutEdgeIt& next(OutEdgeIt& it) const |
160 OutEdgeIt& next(OutEdgeIt& it) const |
146 { it.n=edges[it.n].next_out; return it; } |
161 { it.n=edges[it.n].next_out; return it; } |
147 InEdgeIt& next(InEdgeIt& it) const |
162 InEdgeIt& next(InEdgeIt& it) const |
148 { it.n=edges[it.n].next_in; return it; } |
163 { it.n=edges[it.n].next_in; return it; } |
149 EdgeIt& next(EdgeIt& it) const { --it.n; return it; } |
164 EdgeIt& next(EdgeIt& it) const { |
|
165 if(edges[it.n].next_in!=-1) { |
|
166 it.n=edges[it.n].next_in; |
|
167 } |
|
168 else { |
|
169 int n; |
|
170 for(n=nodes[edges[it.n].head].next; |
|
171 n!=-1 && nodes[n].first_in == -1; |
|
172 n = nodes[n].next) ; |
|
173 it.n = (n==-1)?-1:nodes[n].first_in; |
|
174 } |
|
175 return it; |
|
176 } |
150 |
177 |
151 int id(Node v) const { return v.n; } |
178 int id(Node v) const { return v.n; } |
152 int id(Edge e) const { return e.n; } |
179 int id(Edge e) const { return e.n; } |
153 |
180 |
|
181 /// Adds a new node to the graph. |
|
182 |
|
183 /// \todo It adds the nodes in a reversed order. |
|
184 /// (i.e. the lastly added node becomes the first.) |
154 Node addNode() { |
185 Node addNode() { |
155 Node n; n.n=nodes.size(); |
186 int n; |
156 nodes.push_back(NodeT()); //FIXME: Hmmm... |
187 |
157 |
188 if(first_free_node==-1) |
|
189 { |
|
190 n = nodes.size(); |
|
191 nodes.push_back(NodeT()); |
|
192 } |
|
193 else { |
|
194 n = first_free_node; |
|
195 first_free_node = nodes[n].next; |
|
196 } |
|
197 |
|
198 nodes[n].next = first_node; |
|
199 if(first_node != -1) nodes[first_node].prev = n; |
|
200 first_node = n; |
|
201 nodes[n].prev = -1; |
|
202 |
|
203 nodes[n].first_in = nodes[n].first_out = -1; |
|
204 |
|
205 Node nn; nn.n=n; |
|
206 |
|
207 //Update dynamic maps |
158 for(std::vector<DynMapBase<Node> * >::iterator i=dyn_node_maps.begin(); |
208 for(std::vector<DynMapBase<Node> * >::iterator i=dyn_node_maps.begin(); |
159 i!=dyn_node_maps.end(); ++i) (**i).add(n.n); |
209 i!=dyn_node_maps.end(); ++i) (**i).add(nn); |
160 |
210 |
161 return n; |
211 return nn; |
162 } |
212 } |
163 |
213 |
164 Edge addEdge(Node u, Node v) { |
214 Edge addEdge(Node u, Node v) { |
165 Edge e; e.n=edges.size(); edges.push_back(EdgeT()); //FIXME: Hmmm... |
215 int n; |
166 edges[e.n].tail=u.n; edges[e.n].head=v.n; |
216 |
167 edges[e.n].next_out=nodes[u.n].first_out; |
217 if(first_free_edge==-1) |
168 edges[e.n].next_in=nodes[v.n].first_in; |
218 { |
169 nodes[u.n].first_out=nodes[v.n].first_in=e.n; |
219 n = edges.size(); |
170 |
220 edges.push_back(EdgeT()); |
|
221 } |
|
222 else { |
|
223 n = first_free_edge; |
|
224 first_free_edge = edges[n].next_in; |
|
225 } |
|
226 |
|
227 edges[n].tail = u.n; edges[n].head = v.n; |
|
228 |
|
229 edges[n].next_out = nodes[u.n].first_out; |
|
230 if(nodes[u.n].first_out != -1) edges[nodes[u.n].first_out].prev_out = n; |
|
231 edges[n].next_in = nodes[v.n].first_in; |
|
232 if(nodes[v.n].first_in != -1) edges[nodes[v.n].first_in].prev_in = n; |
|
233 edges[n].prev_in = edges[n].prev_out = -1; |
|
234 |
|
235 nodes[u.n].first_out = nodes[v.n].first_in = n; |
|
236 |
|
237 Edge e; e.n=n; |
|
238 |
|
239 //Update dynamic maps |
171 for(std::vector<DynMapBase<Edge> * >::iterator i=dyn_edge_maps.begin(); |
240 for(std::vector<DynMapBase<Edge> * >::iterator i=dyn_edge_maps.begin(); |
172 i!=dyn_edge_maps.end(); ++i) (**i).add(e); |
241 i!=dyn_edge_maps.end(); ++i) (**i).add(e); |
173 |
242 |
174 return e; |
243 return e; |
175 } |
244 } |
176 |
245 |
177 void clear() {nodes.clear();edges.clear();} |
246 private: |
|
247 void eraseEdge(int n) { |
|
248 |
|
249 if(edges[n].next_in!=-1) |
|
250 edges[edges[n].next_in].prev_in = edges[n].prev_in; |
|
251 if(edges[n].prev_in!=-1) |
|
252 edges[edges[n].prev_in].next_in = edges[n].next_in; |
|
253 else nodes[edges[n].head].first_in = edges[n].next_in; |
|
254 |
|
255 if(edges[n].next_out!=-1) |
|
256 edges[edges[n].next_out].prev_out = edges[n].prev_out; |
|
257 if(edges[n].prev_out!=-1) |
|
258 edges[edges[n].prev_out].next_out = edges[n].next_out; |
|
259 else nodes[edges[n].tail].first_out = edges[n].next_out; |
|
260 |
|
261 edges[n].next_in = first_free_edge; |
|
262 first_free_edge = -1; |
|
263 |
|
264 //Update dynamic maps |
|
265 Edge e; e.n=n; |
|
266 for(std::vector<DynMapBase<Edge> * >::iterator i=dyn_edge_maps.begin(); |
|
267 i!=dyn_edge_maps.end(); ++i) (**i).erase(e); |
|
268 } |
|
269 |
|
270 public: |
|
271 |
|
272 void erase(Node nn) { |
|
273 int n=nn.n; |
|
274 |
|
275 int m; |
|
276 while((m=nodes[n].first_in)!=-1) eraseEdge(m); |
|
277 while((m=nodes[n].first_out)!=-1) eraseEdge(m); |
|
278 |
|
279 if(nodes[n].next != -1) nodes[nodes[n].next].prev = nodes[n].prev; |
|
280 if(nodes[n].prev != -1) nodes[nodes[n].prev].next = nodes[n].next; |
|
281 else first_node = nodes[n].next; |
|
282 |
|
283 nodes[n].next = first_free_node; |
|
284 first_free_node = n; |
|
285 |
|
286 //Update dynamic maps |
|
287 for(std::vector<DynMapBase<Node> * >::iterator i=dyn_node_maps.begin(); |
|
288 i!=dyn_node_maps.end(); ++i) (**i).erase(nn); |
|
289 } |
|
290 |
|
291 void erase(Edge e) { eraseEdge(e.n); } |
|
292 |
|
293 ///\bug Dynamic maps must be updated! |
|
294 /// |
|
295 void clear() { |
|
296 nodes.clear();edges.clear(); |
|
297 first_node=first_free_node=first_free_edge=-1; |
|
298 } |
178 |
299 |
179 class Node { |
300 class Node { |
180 friend class SmartGraph; |
301 friend class ListGraph; |
181 template <typename T> friend class NodeMap; |
302 template <typename T> friend class NodeMap; |
182 |
303 |
183 friend class Edge; |
304 friend class Edge; |
184 friend class OutEdgeIt; |
305 friend class OutEdgeIt; |
185 friend class InEdgeIt; |
306 friend class InEdgeIt; |
186 friend class SymEdge; |
307 friend class SymEdge; |
187 |
308 |
188 protected: |
309 protected: |
189 int n; |
310 int n; |
190 friend int SmartGraph::id(Node v) const; |
311 friend int ListGraph::id(Node v) const; |
191 Node(int nn) {n=nn;} |
312 Node(int nn) {n=nn;} |
192 public: |
313 public: |
193 Node() {} |
314 Node() {} |
194 Node (Invalid i) { n=-1; } |
315 Node (Invalid i) { n=-1; } |
195 bool operator==(const Node i) const {return n==i.n;} |
316 bool operator==(const Node i) const {return n==i.n;} |
196 bool operator!=(const Node i) const {return n!=i.n;} |
317 bool operator!=(const Node i) const {return n!=i.n;} |
197 bool operator<(const Node i) const {return n<i.n;} |
318 bool operator<(const Node i) const {return n<i.n;} |
198 }; |
319 }; |
199 |
320 |
200 class NodeIt : public Node { |
321 class NodeIt : public Node { |
201 friend class SmartGraph; |
322 friend class ListGraph; |
202 public: |
323 public: |
203 NodeIt(const SmartGraph& G) : Node(G.nodes.size()?0:-1) { } |
324 NodeIt(const ListGraph& G) : Node(G.first_node) { } |
204 NodeIt() : Node() { } |
325 NodeIt() : Node() { } |
205 }; |
326 }; |
206 |
327 |
207 class Edge { |
328 class Edge { |
208 friend class SmartGraph; |
329 friend class ListGraph; |
209 template <typename T> friend class EdgeMap; |
330 template <typename T> friend class EdgeMap; |
210 |
331 |
211 //template <typename T> friend class SymSmartGraph::SymEdgeMap; |
332 //template <typename T> friend class SymListGraph::SymEdgeMap; |
212 //friend Edge SymSmartGraph::opposite(Edge) const; |
333 //friend Edge SymListGraph::opposite(Edge) const; |
213 |
334 |
214 friend class Node; |
335 friend class Node; |
215 friend class NodeIt; |
336 friend class NodeIt; |
216 protected: |
337 protected: |
217 int n; |
338 int n; |
218 friend int SmartGraph::id(Edge e) const; |
339 friend int ListGraph::id(Edge e) const; |
219 |
340 |
220 Edge(int nn) {n=nn;} |
341 Edge(int nn) {n=nn;} |
221 public: |
342 public: |
222 Edge() { } |
343 Edge() { } |
223 Edge (Invalid) { n=-1; } |
344 Edge (Invalid) { n=-1; } |
224 bool operator==(const Edge i) const {return n==i.n;} |
345 bool operator==(const Edge i) const {return n==i.n;} |
225 bool operator!=(const Edge i) const {return n!=i.n;} |
346 bool operator!=(const Edge i) const {return n!=i.n;} |
226 bool operator<(const Edge i) const {return n<i.n;} |
347 bool operator<(const Edge i) const {return n<i.n;} |
227 ///\bug This is a workaround until somebody tells me how to |
348 ///\bug This is a workaround until somebody tells me how to |
228 ///make class \c SymSmartGraph::SymEdgeMap friend of Edge |
349 ///make class \c SymListGraph::SymEdgeMap friend of Edge |
229 int &idref() {return n;} |
350 int &idref() {return n;} |
230 const int &idref() const {return n;} |
351 const int &idref() const {return n;} |
231 }; |
352 }; |
232 |
353 |
233 class EdgeIt : public Edge { |
354 class EdgeIt : public Edge { |
234 friend class SmartGraph; |
355 friend class ListGraph; |
235 public: |
356 public: |
236 EdgeIt(const SmartGraph& G) : Edge(G.edges.size()-1) { } |
357 EdgeIt(const ListGraph& G) : Edge() { |
|
358 int m; |
|
359 for(m=G.first_node; |
|
360 m!=-1 && G.nodes[m].first_in == -1; m = G.nodes[m].next); |
|
361 n = (m==-1)?-1:G.nodes[m].first_in; |
|
362 } |
237 EdgeIt (Invalid i) : Edge(i) { } |
363 EdgeIt (Invalid i) : Edge(i) { } |
238 EdgeIt() : Edge() { } |
364 EdgeIt() : Edge() { } |
239 ///\bug This is a workaround until somebody tells me how to |
365 ///\bug This is a workaround until somebody tells me how to |
240 ///make class \c SymSmartGraph::SymEdgeMap friend of Edge |
366 ///make class \c SymListGraph::SymEdgeMap friend of Edge |
241 int &idref() {return n;} |
367 int &idref() {return n;} |
242 }; |
368 }; |
243 |
369 |
244 class OutEdgeIt : public Edge { |
370 class OutEdgeIt : public Edge { |
245 friend class SmartGraph; |
371 friend class ListGraph; |
246 public: |
372 public: |
247 OutEdgeIt() : Edge() { } |
373 OutEdgeIt() : Edge() { } |
248 OutEdgeIt (Invalid i) : Edge(i) { } |
374 OutEdgeIt (Invalid i) : Edge(i) { } |
249 |
375 |
250 OutEdgeIt(const SmartGraph& G,const Node v) |
376 OutEdgeIt(const ListGraph& G,const Node v) |
251 : Edge(G.nodes[v.n].first_out) {} |
377 : Edge(G.nodes[v.n].first_out) {} |
252 }; |
378 }; |
253 |
379 |
254 class InEdgeIt : public Edge { |
380 class InEdgeIt : public Edge { |
255 friend class SmartGraph; |
381 friend class ListGraph; |
256 public: |
382 public: |
257 InEdgeIt() : Edge() { } |
383 InEdgeIt() : Edge() { } |
258 InEdgeIt (Invalid i) : Edge(i) { } |
384 InEdgeIt (Invalid i) : Edge(i) { } |
259 InEdgeIt(const SmartGraph& G,Node v) :Edge(G.nodes[v.n].first_in){} |
385 InEdgeIt(const ListGraph& G,Node v) :Edge(G.nodes[v.n].first_in){} |
260 }; |
386 }; |
261 |
387 |
262 template <typename T> class NodeMap : public DynMapBase<Node> |
388 template <typename T> class NodeMap : public DynMapBase<Node> |
263 { |
389 { |
264 std::vector<T> container; |
390 std::vector<T> container; |
265 |
391 |
266 public: |
392 public: |
267 typedef T ValueType; |
393 typedef T ValueType; |
268 typedef Node KeyType; |
394 typedef Node KeyType; |
269 |
395 |
270 NodeMap(const SmartGraph &_G) : |
396 NodeMap(const ListGraph &_G) : |
271 DynMapBase<Node>(_G), container(_G.maxNodeId()) |
397 DynMapBase<Node>(_G), container(_G.maxNodeId()) |
272 { |
398 { |
273 G->dyn_node_maps.push_back(this); |
399 G->dyn_node_maps.push_back(this); |
274 } |
400 } |
275 NodeMap(const SmartGraph &_G,const T &t) : |
401 NodeMap(const ListGraph &_G,const T &t) : |
276 DynMapBase<Node>(_G), container(_G.maxNodeId(),t) |
402 DynMapBase<Node>(_G), container(_G.maxNodeId(),t) |
277 { |
403 { |
278 G->dyn_node_maps.push_back(this); |
404 G->dyn_node_maps.push_back(this); |
279 } |
405 } |
280 |
406 |
444 |
570 |
445 ///The purpose of this graph structure is to handle graphs |
571 ///The purpose of this graph structure is to handle graphs |
446 ///having bidirectional edges. Here the function \c addEdge(u,v) adds a pair |
572 ///having bidirectional edges. Here the function \c addEdge(u,v) adds a pair |
447 ///of oppositely directed edges. |
573 ///of oppositely directed edges. |
448 ///There is a new edge map type called |
574 ///There is a new edge map type called |
449 ///\ref SymSmartGraph::SymEdgeMap "SymEdgeMap" |
575 ///\ref SymListGraph::SymEdgeMap "SymEdgeMap" |
450 ///that complements this |
576 ///that complements this |
451 ///feature by |
577 ///feature by |
452 ///storing shared values for the edge pairs. The usual |
578 ///storing shared values for the edge pairs. The usual |
453 ///\ref GraphSkeleton::EdgeMap "EdgeMap" |
579 ///\ref GraphSkeleton::EdgeMap "EdgeMap" |
454 ///can be used |
580 ///can be used |
455 ///as well. |
581 ///as well. |
456 /// |
582 /// |
457 ///The oppositely directed edge can also be obtained easily |
583 ///The oppositely directed edge can also be obtained easily |
458 ///using \ref opposite. |
584 ///using \ref opposite. |
459 ///\warning It shares the similarity with \ref SmartGraph that |
585 /// |
460 ///it is not possible to delete edges or nodes from the graph. |
586 ///Here erase(Edge) deletes a pair of edges. |
461 //\sa \ref SmartGraph. |
587 /// |
462 |
588 ///\todo this date structure need some reconsiderations. Maybe it |
463 class SymSmartGraph : public SmartGraph |
589 ///should be implemented independently from ListGraph. |
|
590 |
|
591 class SymListGraph : public ListGraph |
464 { |
592 { |
465 public: |
593 public: |
466 template<typename T> class SymEdgeMap; |
594 template<typename T> class SymEdgeMap; |
467 template<typename T> friend class SymEdgeMap; |
595 template<typename T> friend class SymEdgeMap; |
468 |
596 |
469 SymSmartGraph() : SmartGraph() { } |
597 SymListGraph() : ListGraph() { } |
470 SymSmartGraph(const SmartGraph &_g) : SmartGraph(_g) { } |
598 SymListGraph(const ListGraph &_g) : ListGraph(_g) { } |
|
599 ///Adds a pair of oppositely directed edges to the graph. |
471 Edge addEdge(Node u, Node v) |
600 Edge addEdge(Node u, Node v) |
472 { |
601 { |
473 Edge e = SmartGraph::addEdge(u,v); |
602 Edge e = ListGraph::addEdge(u,v); |
474 SmartGraph::addEdge(v,u); |
603 ListGraph::addEdge(v,u); |
475 return e; |
604 return e; |
476 } |
605 } |
477 |
606 |
|
607 void erase(Node n) { ListGraph::erase(n); } |
478 ///The oppositely directed edge. |
608 ///The oppositely directed edge. |
479 |
609 |
480 ///Returns the oppositely directed |
610 ///Returns the oppositely directed |
481 ///pair of the edge \c e. |
611 ///pair of the edge \c e. |
482 Edge opposite(Edge e) const |
612 Edge opposite(Edge e) const |