Check StaticGraphSkeleton, as well.
3 #ifndef HUGO_LIST_GRAPH_H
4 #define HUGO_LIST_GRAPH_H
8 ///\brief ListGraph, SymListGraph, NodeSet and EdgeSet classes.
15 #include "array_map_factory.h"
16 #include "map_registry.h"
18 #include "map_defines.h"
22 /// \addtogroup graphs
25 ///A list graph class.
27 ///This is a simple and fast erasable graph implementation.
29 ///It conforms to the graph interface documented under
30 ///the description of \ref GraphSkeleton.
31 ///\sa \ref GraphSkeleton.
34 //Nodes are double linked.
35 //The free nodes are only single linked using the "next" field.
38 int first_in,first_out;
42 //Edges are double linked.
43 //The free edges are only single linked using the "next_in" field.
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) {}
53 std::vector<NodeT> nodes;
58 std::vector<EdgeT> edges;
69 typedef ListGraph Graph;
78 CREATE_MAP_REGISTRIES;
79 CREATE_MAPS(ArrayMapFactory);
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),
87 first_free_edge(_g.first_free_edge) {}
90 int nodeNum() const { return nodes.size(); } //FIXME: What is this?
91 int edgeNum() const { return edges.size(); } //FIXME: What is this?
93 ///Set the expected number of edges
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); };
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?
107 Node tail(Edge e) const { return edges[e.n].tail; }
108 Node head(Edge e) const { return edges[e.n].head; }
110 Node aNode(OutEdgeIt e) const { return edges[e.n].tail; }
111 Node aNode(InEdgeIt e) const { return edges[e.n].head; }
113 Node bNode(OutEdgeIt e) const { return edges[e.n].head; }
114 Node bNode(InEdgeIt e) const { return edges[e.n].tail; }
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; }
125 // template< typename It >
126 // It first() const { It e; first(e); return e; }
128 // template< typename It >
129 // It first(Node v) const { It e; first(e,v); return e; }
131 bool valid(Edge e) const { return e.n!=-1; }
132 bool valid(Node n) const { return n.n!=-1; }
134 void setInvalid(Edge &e) { e.n=-1; }
135 void setInvalid(Node &n) { n.n=-1; }
137 template <typename It> It getNext(It it) const
138 { It tmp(it); return next(tmp); }
140 NodeIt& next(NodeIt& it) const {
141 it.n=nodes[it.n].next;
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;
154 for(n=nodes[edges[it.n].head].next;
155 n!=-1 && nodes[n].first_in == -1;
157 it.n = (n==-1)?-1:nodes[n].first_in;
162 int id(Node v) const { return v.n; }
163 int id(Edge e) const { return e.n; }
165 /// Adds a new node to the graph.
167 /// \todo It adds the nodes in a reversed order.
168 /// (i.e. the lastly added node becomes the first.)
172 if(first_free_node==-1)
175 nodes.push_back(NodeT());
179 first_free_node = nodes[n].next;
182 nodes[n].next = first_node;
183 if(first_node != -1) nodes[first_node].prev = n;
187 nodes[n].first_in = nodes[n].first_out = -1;
191 //Update dynamic maps
197 Edge addEdge(Node u, Node v) {
200 if(first_free_edge==-1)
203 edges.push_back(EdgeT());
207 first_free_edge = edges[n].next_in;
210 edges[n].tail = u.n; edges[n].head = v.n;
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;
218 nodes[u.n].first_out = nodes[v.n].first_in = n;
222 //Update dynamic maps
229 void eraseEdge(int n) {
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].head].first_in = edges[n].next_in;
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].tail].first_out = edges[n].next_out;
243 edges[n].next_in = first_free_edge;
246 //Update dynamic maps
252 void erase(Node nn) {
256 while((m=nodes[n].first_in)!=-1) eraseEdge(m);
257 while((m=nodes[n].first_out)!=-1) eraseEdge(m);
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;
263 nodes[n].next = first_free_node;
266 //Update dynamic maps
275 ///\bug Dynamic maps must be updated!
278 nodes.clear();edges.clear();
279 first_node=first_free_node=first_free_edge=-1;
283 friend class ListGraph;
284 template <typename T> friend class NodeMap;
287 friend class OutEdgeIt;
288 friend class InEdgeIt;
289 friend class SymEdge;
293 friend int ListGraph::id(Node v) const;
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;}
303 class NodeIt : public Node {
304 friend class ListGraph;
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) { }
314 friend class ListGraph;
315 template <typename T> friend class EdgeMap;
317 //template <typename T> friend class SymListGraph::SymEdgeMap;
318 //friend Edge SymListGraph::opposite(Edge) const;
324 friend int ListGraph::id(Edge e) const;
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;}
339 class EdgeIt : public Edge {
340 friend class ListGraph;
342 EdgeIt(const ListGraph& G) : Edge() {
345 m!=-1 && G.nodes[m].first_in == -1; m = G.nodes[m].next);
346 n = (m==-1)?-1:G.nodes[m].first_in;
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;}
355 class OutEdgeIt : public Edge {
356 friend class ListGraph;
358 OutEdgeIt() : Edge() { }
359 OutEdgeIt (Invalid i) : Edge(i) { }
361 OutEdgeIt(const ListGraph& G,const Node v)
362 : Edge(G.nodes[v.n].first_out) {}
365 class InEdgeIt : public Edge {
366 friend class ListGraph;
368 InEdgeIt() : Edge() { }
369 InEdgeIt (Invalid i) : Edge(i) { }
370 InEdgeIt(const ListGraph& G,Node v) :Edge(G.nodes[v.n].first_in) {}
375 ///Graph for bidirectional edges.
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
384 ///storing shared values for the edge pairs. The usual
385 ///\ref GraphSkeleton::EdgeMap "EdgeMap"
389 ///The oppositely directed edge can also be obtained easily
390 ///using \ref opposite.
392 ///Here erase(Edge) deletes a pair of edges.
394 ///\todo this date structure need some reconsiderations. Maybe it
395 ///should be implemented independently from ListGraph.
399 #endif //HUGO_LIST_GRAPH_H