jacint@131
|
1 |
// -*- mode:C++ -*-
|
jacint@131
|
2 |
|
jacint@131
|
3 |
#ifndef J_GRAPH_H
|
jacint@131
|
4 |
#define J_GRAPH_H
|
jacint@131
|
5 |
|
jacint@131
|
6 |
#include <iostream>
|
jacint@131
|
7 |
#include <vector>
|
jacint@131
|
8 |
|
jacint@131
|
9 |
namespace hugo {
|
jacint@131
|
10 |
|
jacint@131
|
11 |
class JGraph {
|
jacint@131
|
12 |
|
jacint@131
|
13 |
struct NodeT
|
jacint@131
|
14 |
{
|
jacint@131
|
15 |
int in, out;
|
jacint@131
|
16 |
NodeT() : in(), out() {}
|
jacint@131
|
17 |
};
|
jacint@131
|
18 |
|
jacint@131
|
19 |
struct EdgeT
|
jacint@131
|
20 |
{
|
jacint@131
|
21 |
int head, tail, in, out;
|
jacint@131
|
22 |
};
|
jacint@131
|
23 |
|
jacint@131
|
24 |
|
jacint@131
|
25 |
std::vector<NodeT> nodes;
|
jacint@131
|
26 |
std::vector<EdgeT> edges;
|
jacint@131
|
27 |
|
jacint@131
|
28 |
|
jacint@131
|
29 |
/* template <typename Key> class DynMapBase
|
jacint@131
|
30 |
{
|
jacint@131
|
31 |
protected:
|
jacint@131
|
32 |
SmartGraph* G;
|
jacint@131
|
33 |
public:
|
jacint@131
|
34 |
virtual void add(const Key k) = NULL;
|
jacint@131
|
35 |
virtual void erase(const Key k) = NULL;
|
jacint@131
|
36 |
DynMapBase(SmartGraph &_G) : G(&_G) {}
|
jacint@131
|
37 |
virtual ~DynMapBase() {}
|
jacint@131
|
38 |
friend class SmartGraph;
|
jacint@131
|
39 |
};
|
jacint@131
|
40 |
|
jacint@131
|
41 |
template <typename T> class DynEdgeMap;
|
jacint@131
|
42 |
template <typename T> class DynEdgeMap;
|
jacint@131
|
43 |
*/
|
jacint@131
|
44 |
|
jacint@131
|
45 |
public:
|
jacint@131
|
46 |
|
jacint@131
|
47 |
class TrivNodeIt;
|
jacint@131
|
48 |
class TrivEdgeIt;
|
jacint@131
|
49 |
class NodeIt;
|
jacint@131
|
50 |
class EdgeIt;
|
jacint@131
|
51 |
class OutEdgeIt;
|
jacint@131
|
52 |
class InEdgeIt;
|
jacint@131
|
53 |
|
jacint@131
|
54 |
/* protected:
|
jacint@131
|
55 |
std::vector<DynMapBase<NodeIt> * > dyn_node_maps;
|
jacint@131
|
56 |
std::vector<DynMapBase<EdgeIt> * > dyn_edge_maps;
|
jacint@131
|
57 |
*/
|
jacint@131
|
58 |
|
jacint@131
|
59 |
template <typename T> class NodeMap;
|
jacint@131
|
60 |
template <typename T> class EdgeMap;
|
jacint@131
|
61 |
|
jacint@131
|
62 |
public:
|
jacint@131
|
63 |
|
jacint@131
|
64 |
JGraph() : nodes(1), edges(1) {
|
jacint@131
|
65 |
edges[0].head=0;
|
jacint@131
|
66 |
edges[0].tail=0;
|
jacint@131
|
67 |
edges[0].in=0; //numEdges (numNodes is maintained in nodes[0].in)
|
jacint@131
|
68 |
edges[0].out=0;
|
jacint@131
|
69 |
}
|
jacint@131
|
70 |
|
jacint@131
|
71 |
|
jacint@131
|
72 |
/* ~SmartGraph()
|
jacint@131
|
73 |
{
|
jacint@131
|
74 |
for(std::vector<DynMapBase<NodeIt> * >::iterator i=dyn_node_maps.begin();
|
jacint@131
|
75 |
i!=dyn_node_maps.end(); ++i) (**i).G=NULL;
|
jacint@131
|
76 |
for(std::vector<DynMapBase<EdgeIt> * >::iterator i=dyn_edge_maps.begin();
|
jacint@131
|
77 |
i!=dyn_edge_maps.end(); ++i) (**i).G=NULL;
|
jacint@131
|
78 |
}*/
|
jacint@131
|
79 |
|
jacint@131
|
80 |
int numNodes() const { return nodes[0].in; }
|
jacint@131
|
81 |
int numEdges() const { return edges[0].in; }
|
jacint@131
|
82 |
|
jacint@131
|
83 |
TrivNodeIt tail(TrivEdgeIt e) const { return edges[e.n].tail; }
|
jacint@131
|
84 |
TrivNodeIt head(TrivEdgeIt e) const { return edges[e.n].head; }
|
jacint@131
|
85 |
|
jacint@131
|
86 |
/* EachNodeIt& getFirst(EachNodeIt& v) const {
|
jacint@131
|
87 |
v=EachNodeIt(*this); return v; }
|
jacint@131
|
88 |
EachEdgeIt& getFirst(EachEdgeIt& e) const {
|
jacint@131
|
89 |
e=EachEdgeIt(*this); return e; }
|
jacint@131
|
90 |
OutEdgeIt& getFirst(OutEdgeIt& e, const NodeIt v) const {
|
jacint@131
|
91 |
e=OutEdgeIt(*this,v); return e; }
|
jacint@131
|
92 |
InEdgeIt& getFirst(InEdgeIt& e, const NodeIt v) const {
|
jacint@131
|
93 |
e=InEdgeIt(*this,v); return e; }
|
jacint@131
|
94 |
*/
|
jacint@131
|
95 |
|
jacint@131
|
96 |
NodeIt firstNode() const {
|
jacint@131
|
97 |
return NodeIt( numNodes() );
|
jacint@131
|
98 |
}
|
jacint@131
|
99 |
EdgeIt firstEdge() const {
|
jacint@131
|
100 |
return EdgeIt( numEdges() );
|
jacint@131
|
101 |
}
|
jacint@131
|
102 |
InEdgeIt firstIn(TrivNodeIt v) const {
|
jacint@131
|
103 |
return InEdgeIt(nodes[v.n].in);
|
jacint@131
|
104 |
}
|
jacint@131
|
105 |
OutEdgeIt firstOut(TrivNodeIt v) const {
|
jacint@131
|
106 |
return OutEdgeIt(nodes[v.n].out);
|
jacint@131
|
107 |
}
|
jacint@131
|
108 |
|
jacint@131
|
109 |
|
jacint@131
|
110 |
|
jacint@131
|
111 |
void next(NodeIt& it) const {--it.n;}
|
jacint@131
|
112 |
void next(OutEdgeIt& it) const { it.n=edges[it.n].out; }
|
jacint@131
|
113 |
void next(InEdgeIt& it) const { it.n=edges[it.n].in; }
|
jacint@131
|
114 |
void next(EdgeIt& it) const {--it.n;}
|
jacint@131
|
115 |
|
jacint@131
|
116 |
int id(TrivNodeIt v) const { return v.n; }
|
jacint@131
|
117 |
int id(TrivEdgeIt e) const { return e.n; }
|
jacint@131
|
118 |
|
jacint@131
|
119 |
TrivNodeIt addNode() {
|
jacint@131
|
120 |
TrivNodeIt n;
|
jacint@131
|
121 |
n.n=++nodes[0].in;
|
jacint@131
|
122 |
nodes.push_back(NodeT()); //FIXME
|
jacint@131
|
123 |
|
jacint@131
|
124 |
/* for(std::vector<DynMapBase<NodeIt> * >::iterator i=dyn_node_maps.begin();
|
jacint@131
|
125 |
i!=dyn_node_maps.end(); ++i) (**i).add(n.n);*/
|
jacint@131
|
126 |
|
jacint@131
|
127 |
return n;
|
jacint@131
|
128 |
}
|
jacint@131
|
129 |
|
jacint@131
|
130 |
|
jacint@131
|
131 |
TrivEdgeIt addEdge(TrivNodeIt u, TrivNodeIt v) {
|
jacint@131
|
132 |
if ( u && v ) {
|
jacint@131
|
133 |
TrivEdgeIt e;
|
jacint@131
|
134 |
e.n=++edges[0].in;
|
jacint@131
|
135 |
edges.push_back(EdgeT()); //FIXME: Hmmm...
|
jacint@131
|
136 |
edges[e.n].tail=u.n; edges[e.n].head=v.n;
|
jacint@131
|
137 |
edges[e.n].out=nodes[u.n].out;
|
jacint@131
|
138 |
edges[e.n].in=nodes[v.n].in;
|
jacint@131
|
139 |
nodes[u.n].out=nodes[v.n].in=e.n;
|
jacint@131
|
140 |
return e;
|
jacint@131
|
141 |
}
|
jacint@131
|
142 |
else return TrivEdgeIt();
|
jacint@131
|
143 |
|
jacint@131
|
144 |
/* for(std::vector<DynMapBase<EdgeIt> * >::iterator i=dyn_edge_maps.begin();
|
jacint@131
|
145 |
i!=dyn_edge_maps.end(); ++i) (**i).add(e.n);*/
|
jacint@131
|
146 |
|
jacint@131
|
147 |
|
jacint@131
|
148 |
}
|
jacint@131
|
149 |
|
jacint@131
|
150 |
|
jacint@131
|
151 |
void clear() {
|
jacint@131
|
152 |
nodes.resize(1);
|
jacint@131
|
153 |
edges.resize(1); edges[0].in=0;
|
jacint@131
|
154 |
}
|
jacint@131
|
155 |
|
jacint@131
|
156 |
|
jacint@131
|
157 |
class TrivNodeIt {
|
jacint@131
|
158 |
friend class JGraph;
|
jacint@131
|
159 |
template <typename T> friend class NodeMap;
|
jacint@131
|
160 |
|
jacint@131
|
161 |
friend class TrivEdgeIt;
|
jacint@131
|
162 |
friend class OutEdgeIt;
|
jacint@131
|
163 |
friend class InEdgeIt;
|
jacint@131
|
164 |
|
jacint@131
|
165 |
protected:
|
jacint@131
|
166 |
int n;
|
jacint@131
|
167 |
public:
|
jacint@131
|
168 |
TrivNodeIt() : n() {}
|
jacint@131
|
169 |
TrivNodeIt(int number) {n=number;}
|
jacint@131
|
170 |
bool operator==(const TrivNodeIt i) const {return n==i.n;}
|
jacint@131
|
171 |
bool operator!=(const TrivNodeIt i) const {return n!=i.n;}
|
jacint@131
|
172 |
|
jacint@131
|
173 |
operator bool() const { return n!=0; }
|
jacint@131
|
174 |
|
jacint@131
|
175 |
};
|
jacint@131
|
176 |
|
jacint@131
|
177 |
|
jacint@131
|
178 |
class NodeIt : public TrivNodeIt {
|
jacint@131
|
179 |
friend class JGraph;
|
jacint@131
|
180 |
public:
|
jacint@131
|
181 |
NodeIt() : TrivNodeIt() { }
|
jacint@131
|
182 |
NodeIt(int i) : TrivNodeIt(i) { }
|
jacint@131
|
183 |
operator bool() const { return n!=0; }
|
jacint@131
|
184 |
};
|
jacint@131
|
185 |
|
jacint@131
|
186 |
|
jacint@131
|
187 |
class TrivEdgeIt {
|
jacint@131
|
188 |
friend class JGraph;
|
jacint@131
|
189 |
template <typename T> friend class EdgeMap;
|
jacint@131
|
190 |
|
jacint@131
|
191 |
friend class TrivNodeIt;
|
jacint@131
|
192 |
friend class NodeIt;
|
jacint@131
|
193 |
protected:
|
jacint@131
|
194 |
int n;
|
jacint@131
|
195 |
public:
|
jacint@131
|
196 |
TrivEdgeIt() : n() { }
|
jacint@131
|
197 |
TrivEdgeIt(int number) {n=number;}
|
jacint@131
|
198 |
bool operator==(const TrivEdgeIt i) const {return n==i.n;}
|
jacint@131
|
199 |
bool operator!=(const TrivEdgeIt i) const {return n!=i.n;}
|
jacint@131
|
200 |
operator bool() const { return n!=0; }
|
jacint@131
|
201 |
|
jacint@131
|
202 |
};
|
jacint@131
|
203 |
|
jacint@131
|
204 |
|
jacint@131
|
205 |
class EdgeIt : public TrivEdgeIt {
|
jacint@131
|
206 |
friend class JGraph;
|
jacint@131
|
207 |
public:
|
jacint@131
|
208 |
EdgeIt() : TrivEdgeIt() { }
|
jacint@131
|
209 |
EdgeIt(int i) : TrivEdgeIt(i) { }
|
jacint@131
|
210 |
operator bool() const { return n!=0; }
|
jacint@131
|
211 |
};
|
jacint@131
|
212 |
|
jacint@131
|
213 |
|
jacint@131
|
214 |
class OutEdgeIt : public TrivEdgeIt {
|
jacint@131
|
215 |
friend class JGraph;
|
jacint@131
|
216 |
public:
|
jacint@131
|
217 |
OutEdgeIt() : TrivEdgeIt() { }
|
jacint@131
|
218 |
OutEdgeIt(int i) : TrivEdgeIt(i) { }
|
jacint@131
|
219 |
};
|
jacint@131
|
220 |
|
jacint@131
|
221 |
|
jacint@131
|
222 |
class InEdgeIt : public TrivEdgeIt {
|
jacint@131
|
223 |
friend class JGraph;
|
jacint@131
|
224 |
public:
|
jacint@131
|
225 |
InEdgeIt() : TrivEdgeIt() { }
|
jacint@131
|
226 |
InEdgeIt(int i) : TrivEdgeIt(i) { }
|
jacint@131
|
227 |
};
|
jacint@131
|
228 |
|
jacint@131
|
229 |
|
jacint@131
|
230 |
// Map types
|
jacint@131
|
231 |
|
jacint@131
|
232 |
template <typename T>
|
jacint@131
|
233 |
class NodeMap {
|
jacint@131
|
234 |
const JGraph& G;
|
jacint@131
|
235 |
std::vector<T> container;
|
jacint@131
|
236 |
public:
|
jacint@131
|
237 |
NodeMap(const JGraph& _G) : G(_G), container( G.numNodes()+1 ) { }
|
jacint@131
|
238 |
NodeMap(const JGraph& _G, T a) :
|
jacint@131
|
239 |
G(_G), container(G.numNodes()+1, a) { }
|
jacint@131
|
240 |
void set(TrivNodeIt n, T a) { container[n.n]=a; }
|
jacint@131
|
241 |
T get(TrivNodeIt n) const { return container[n.n]; }
|
jacint@131
|
242 |
/*T& operator[](NodeIt n) { return container[n.n]; }
|
jacint@131
|
243 |
const T& operator[](NodeIt n) const { return container[n.n]; }*/
|
jacint@131
|
244 |
void update() { container.resize(G.numNodes()+1); }
|
jacint@131
|
245 |
void update(T a) { container.resize(G.numNodes()+1, a); }
|
jacint@131
|
246 |
};
|
jacint@131
|
247 |
|
jacint@131
|
248 |
template <typename T>
|
jacint@131
|
249 |
class EdgeMap {
|
jacint@131
|
250 |
const JGraph& G;
|
jacint@131
|
251 |
std::vector<T> container;
|
jacint@131
|
252 |
public:
|
jacint@131
|
253 |
EdgeMap(const JGraph& _G) : G(_G), container(G.numEdges()+1) { }
|
jacint@131
|
254 |
EdgeMap(const JGraph& _G, T a) :
|
jacint@131
|
255 |
G(_G), container(G.numEdges()+1, a) { }
|
jacint@131
|
256 |
void set(TrivEdgeIt e, T a) { container[e.n]=a; }
|
jacint@131
|
257 |
T get(TrivEdgeIt e) const { return container[e.n]; }
|
jacint@131
|
258 |
/*T& operator[](EdgeIt e) { return container[e.n]; }
|
jacint@131
|
259 |
const T& operator[](EdgeIt e) const { return container[e.n]; } */
|
jacint@131
|
260 |
void update() { container.resize(G.numEdges()+1); }
|
jacint@131
|
261 |
void update(T a) { container.resize(G.numEdges()+1, a); }
|
jacint@131
|
262 |
};
|
jacint@131
|
263 |
|
jacint@131
|
264 |
/*template <typename T> class DynNodeMap : public DynMapBase<NodeIt>
|
jacint@131
|
265 |
{
|
jacint@131
|
266 |
std::vector<T> container;
|
jacint@131
|
267 |
|
jacint@131
|
268 |
public:
|
jacint@131
|
269 |
typedef T ValueType;
|
jacint@131
|
270 |
typedef NodeIt KeyType;
|
jacint@131
|
271 |
|
jacint@131
|
272 |
DynNodeMap(JGraph &_G) :
|
jacint@131
|
273 |
DynMapBase<NodeIt>(_G), container(_G.maxNodeId())
|
jacint@131
|
274 |
{
|
jacint@131
|
275 |
//FIXME: What if there are empty Id's?
|
jacint@131
|
276 |
//FIXME: Can I use 'this' in a constructor?
|
jacint@131
|
277 |
G->dyn_node_maps.push_back(this);
|
jacint@131
|
278 |
}
|
jacint@131
|
279 |
~DynNodeMap()
|
jacint@131
|
280 |
{
|
jacint@131
|
281 |
if(G) {
|
jacint@131
|
282 |
std::vector<DynMapBase<NodeIt>* >::iterator i;
|
jacint@131
|
283 |
for(i=G->dyn_node_maps.begin();
|
jacint@131
|
284 |
i!=G->dyn_node_maps.end() && *i!=this; ++i) ;
|
jacint@131
|
285 |
//if(*i==this) G->dyn_node_maps.erase(i); //FIXME: Way too slow...
|
jacint@131
|
286 |
//A better way to do that: (Is this really important?)
|
jacint@131
|
287 |
if(*i==this) {
|
jacint@131
|
288 |
*i=G->dyn_node_maps.back();
|
jacint@131
|
289 |
G->dyn_node_maps.pop_back();
|
jacint@131
|
290 |
}
|
jacint@131
|
291 |
}
|
jacint@131
|
292 |
}
|
jacint@131
|
293 |
|
jacint@131
|
294 |
void add(const NodeIt k)
|
jacint@131
|
295 |
{
|
jacint@131
|
296 |
if(k.n>=container.size()) container.resize(k.n+1);
|
jacint@131
|
297 |
}
|
jacint@131
|
298 |
void erase(const NodeIt k)
|
jacint@131
|
299 |
{
|
jacint@131
|
300 |
//FIXME: Please implement me.
|
jacint@131
|
301 |
}
|
jacint@131
|
302 |
|
jacint@131
|
303 |
void set(NodeIt n, T a) { container[n.n]=a; }
|
jacint@131
|
304 |
T get(NodeIt n) const { return container[n.n]; }
|
jacint@131
|
305 |
T& operator[](NodeIt n) { return container[n.n]; }
|
jacint@131
|
306 |
const T& operator[](NodeIt n) const { return container[n.n]; }
|
jacint@131
|
307 |
|
jacint@131
|
308 |
void update() {} //Useless for DynMaps
|
jacint@131
|
309 |
void update(T a) {} //Useless for DynMaps
|
jacint@131
|
310 |
};
|
jacint@131
|
311 |
|
jacint@131
|
312 |
template <typename T> class DynEdgeMap : public DynMapBase<EdgeIt>
|
jacint@131
|
313 |
{
|
jacint@131
|
314 |
std::vector<T> container;
|
jacint@131
|
315 |
|
jacint@131
|
316 |
public:
|
jacint@131
|
317 |
typedef T ValueType;
|
jacint@131
|
318 |
typedef EdgeIt KeyType;
|
jacint@131
|
319 |
|
jacint@131
|
320 |
DynEdgeMap(JGraph &_G) :
|
jacint@131
|
321 |
DynMapBase<EdgeIt>(_G), container(_G.maxEdgeId())
|
jacint@131
|
322 |
{
|
jacint@131
|
323 |
//FIXME: What if there are empty Id's?
|
jacint@131
|
324 |
//FIXME: Can I use 'this' in a constructor?
|
jacint@131
|
325 |
G->dyn_edge_maps.push_back(this);
|
jacint@131
|
326 |
}
|
jacint@131
|
327 |
~DynEdgeMap()
|
jacint@131
|
328 |
{
|
jacint@131
|
329 |
if(G) {
|
jacint@131
|
330 |
std::vector<DynMapBase<EdgeIt>* >::iterator i;
|
jacint@131
|
331 |
for(i=G->dyn_edge_maps.begin();
|
jacint@131
|
332 |
i!=G->dyn_edge_maps.end() && *i!=this; ++i) ;
|
jacint@131
|
333 |
//if(*i==this) G->dyn_edge_maps.erase(i); //Way too slow...
|
jacint@131
|
334 |
//A better way to do that: (Is this really important?)
|
jacint@131
|
335 |
if(*i==this) {
|
jacint@131
|
336 |
*i=G->dyn_edge_maps.back();
|
jacint@131
|
337 |
G->dyn_edge_maps.pop_back();
|
jacint@131
|
338 |
}
|
jacint@131
|
339 |
}
|
jacint@131
|
340 |
}
|
jacint@131
|
341 |
|
jacint@131
|
342 |
void add(const EdgeIt k)
|
jacint@131
|
343 |
{
|
jacint@131
|
344 |
if(k.n>=int(container.size())) container.resize(k.n+1);
|
jacint@131
|
345 |
}
|
jacint@131
|
346 |
void erase(const EdgeIt k)
|
jacint@131
|
347 |
{
|
jacint@131
|
348 |
//FIXME: Please implement me.
|
jacint@131
|
349 |
}
|
jacint@131
|
350 |
|
jacint@131
|
351 |
void set(EdgeIt n, T a) { container[n.n]=a; }
|
jacint@131
|
352 |
T get(EdgeIt n) const { return container[n.n]; }
|
jacint@131
|
353 |
T& operator[](EdgeIt n) { return container[n.n]; }
|
jacint@131
|
354 |
const T& operator[](EdgeIt n) const { return container[n.n]; }
|
jacint@131
|
355 |
|
jacint@131
|
356 |
void update() {} //Useless for DynMaps
|
jacint@131
|
357 |
void update(T a) {} //Useless for DynMaps
|
jacint@131
|
358 |
};*/
|
jacint@131
|
359 |
|
jacint@131
|
360 |
};
|
jacint@131
|
361 |
} //namespace hugo
|
jacint@131
|
362 |
|
jacint@131
|
363 |
#endif //J_GRAPH_H
|