I hope it works. The 'erase' functions hasn't been tested yet.
5 * Class for representing paths in graphs.
20 template<typename Graph>
23 typedef typename Graph::Edge GraphEdge;
24 typedef typename Graph::Node GraphNode;
30 typedef std::vector<GraphEdge> Container;
35 DirPath(const Graph &_G) : gr(&_G) {}
37 /// Subpath defined by two nodes.
38 /// It is an error if the two edges are not in order!
39 DirPath(const DirPath &P, const NodeIt &a, const NodeIt &b);
40 /// Subpath defined by two edges. Contains edges in [a,b)
41 /// It is an error if the two edges are not in order!
42 DirPath(const DirPath &P, const EdgeIt &a, const EdgeIt &b);
44 size_t length() const { return edges.size(); }
45 bool empty() const { return edges.empty(); }
46 GraphNode from() const {
47 return empty() ? INVALID : gr->tail(edges[0]);
49 GraphNode to() const {
50 return empty() ? INVALID : gr->head(edges[length()-1]);
54 It& first(It &i) const { return i=It(*this); }
57 It& nth(It &i, int n) const { return i=It(*this, n); }
60 bool valid(const It &i) const { return i.valid(); }
63 It& next(It &e) const { return ++e; }
66 NodeIt head(const EdgeIt& e) const;
67 NodeIt tail(const EdgeIt& e) const;
70 /*** Iterator classes ***/
78 EdgeIt(Invalid) : idx(-1), p(0) {}
79 EdgeIt(const DirPath &_p, int _idx = 0) :
80 idx(_idx), p(&_p) { validate(); }
82 bool valid() const { return idx!=-1; }
84 operator GraphEdge () const {
85 return valid() ? p->edges[idx] : INVALID;
87 EdgeIt& operator++() { ++idx; validate(); return *this; }
89 bool operator==(const EdgeIt& e) const { return idx==e.idx; }
90 bool operator!=(const EdgeIt& e) const { return idx!=e.idx; }
91 bool operator<(const EdgeIt& e) const { return idx<e.idx; }
94 // FIXME: comparison between signed and unsigned...
95 // Jo ez igy? Vagy esetleg legyen a length() int?
96 void validate() { if( size_t(idx) >= p->length() ) idx=-1; }
100 friend class DirPath;
106 NodeIt(Invalid) : idx(-1), p(0) {}
107 NodeIt(const DirPath &_p, int _idx = 0) :
108 idx(_idx), p(&_p) { validate(); }
110 bool valid() const { return idx!=-1; }
112 operator const GraphEdge& () const {
113 if(idx >= p->length())
116 return p->gr->tail(p->edges[idx]);
120 NodeIt& operator++() { ++idx; validate(); return *this; }
122 bool operator==(const NodeIt& e) const { return idx==e.idx; }
123 bool operator!=(const NodeIt& e) const { return idx!=e.idx; }
124 bool operator<(const NodeIt& e) const { return idx<e.idx; }
127 void validate() { if( size_t(idx) > p->length() ) idx=-1; }
130 friend class Builder;
136 Builder(DirPath &_P) : P(_P) {}
138 bool pushFront(const GraphEdge& e) {
139 if( empty() || P.gr->head(e)==from() ) {
145 bool pushBack(const GraphEdge& e) {
146 if( empty() || P.gr->tail(e)==to() ) {
147 P.edges.push_back(e);
155 P.edges.insert(P.edges.begin(), d.rbegin(), d.rend());
160 ~Builder() { commit(); }
162 // FIXME: Hmm, pontosan hogy is kene ezt csinalni?
163 // Hogy kenyelmes egy ilyet hasznalni?
164 void reserve(size_t r) {
166 P.edges.reserve(P.length()+r);
170 bool empty() { return d.empty() && P.empty(); }
172 GraphNode from() const {
174 return P.gr->tail(d[d.size()-1]);
175 else if( ! P.empty() )
176 return P.gr->tail(P.edges[0]);
180 GraphNode to() const {
182 return P.gr->head(P.edges[P.length()-1]);
183 else if( ! d.empty() )
184 return P.gr->head(d[0]);
203 /**********************************************************************/
206 /* Ennek az allocatorosdinak sokkal jobban utana kene nezni a hasznalata
207 elott. Eleg bonyinak nez ki, ahogyan azokat az STL-ben hasznaljak. */
209 template<typename Graph>
213 typedef typename Graph::Edge GraphEdge;
214 typedef typename Graph::Node GraphNode;
220 // FIXME: ehelyett eleg lenne tarolni ket boolt: a ket szelso el
222 GraphNode _first, _last;
223 typedef std::deque<GraphEdge> Container;
228 DynamicPath(Graph &_G) : G(_G), _first(INVALID), _last(INVALID) {}
230 /// Subpath defined by two nodes.
231 /// Nodes may be in reversed order, then
232 /// we contstruct the reversed path.
233 DynamicPath(const DynamicPath &P, const NodeIt &a, const NodeIt &b);
234 /// Subpath defined by two edges. Contains edges in [a,b)
235 /// It is an error if the two edges are not in order!
236 DynamicPath(const DynamicPath &P, const EdgeIt &a, const EdgeIt &b);
238 size_t length() const { return edges.size(); }
239 GraphNode from() const { return _first; }
240 GraphNode to() const { return _last; }
242 NodeIt& first(NodeIt &n) const { return nth(n, 0); }
243 EdgeIt& first(EdgeIt &e) const { return nth(e, 0); }
244 template<typename It>
251 NodeIt& nth(NodeIt &, size_t) const;
252 EdgeIt& nth(EdgeIt &, size_t) const;
253 template<typename It>
254 It nth(size_t n) const {
260 bool valid(const NodeIt &n) const { return n.idx <= length(); }
261 bool valid(const EdgeIt &e) const { return e.it < edges.end(); }
263 bool isForward(const EdgeIt &e) const { return e.forw; }
265 /// index of a node on the path. Returns length+2 for the invalid NodeIt
266 int index(const NodeIt &n) const { return n.idx; }
267 /// index of an edge on the path. Returns length+1 for the invalid EdgeIt
268 int index(const EdgeIt &e) const { return e.it - edges.begin(); }
270 EdgeIt& next(EdgeIt &e) const;
271 NodeIt& next(NodeIt &n) const;
272 template <typename It>
273 It getNext(It it) const {
274 It tmp(it); return next(tmp);
277 // A path is constructed using the following four functions.
278 // They return false if the requested operation is inconsistent
279 // with the path constructed so far.
280 // If your path has only one edge you MUST set either "from" or "to"!
281 // So you probably SHOULD call it in any case to be safe (and check the
282 // returned value to check if your path is consistent with your idea).
283 bool pushFront(const GraphEdge &e);
284 bool pushBack(const GraphEdge &e);
285 bool setFrom(const GraphNode &n);
286 bool setTo(const GraphNode &n);
288 // WARNING: these two functions return the head/tail of an edge with
289 // respect to the direction of the path!
290 // So G.head(P.graphEdge(e)) == P.graphNode(P.head(e)) holds only if
291 // P.forward(e) is true (or the edge is a loop)!
292 NodeIt head(const EdgeIt& e) const;
293 NodeIt tail(const EdgeIt& e) const;
295 // FIXME: ezeknek valami jobb nev kellene!!!
296 GraphEdge graphEdge(const EdgeIt& e) const;
297 GraphNode graphNode(const NodeIt& n) const;
300 /*** Iterator classes ***/
302 friend class DynamicPath;
304 typename Container::const_iterator it;
307 // FIXME: jarna neki ilyen is...
310 bool forward() const { return forw; }
312 bool operator==(const EdgeIt& e) const { return it==e.it; }
313 bool operator!=(const EdgeIt& e) const { return it!=e.it; }
314 bool operator<(const EdgeIt& e) const { return it<e.it; }
318 friend class DynamicPath;
321 bool tail; // Is this node the tail of the edge with same idx?
324 // FIXME: jarna neki ilyen is...
327 bool operator==(const NodeIt& n) const { return idx==n.idx; }
328 bool operator!=(const NodeIt& n) const { return idx!=n.idx; }
329 bool operator<(const NodeIt& n) const { return idx<n.idx; }
333 bool edgeIncident(const GraphEdge &e, const GraphNode &a,
335 bool connectTwoEdges(const GraphEdge &e, const GraphEdge &f);
338 template<typename Gr>
339 typename DynamicPath<Gr>::EdgeIt&
340 DynamicPath<Gr>::next(DynamicPath::EdgeIt &e) const {
341 if( e.it == edges.end() )
344 GraphNode common_node = ( e.forw ? G.head(*e.it) : G.tail(*e.it) );
347 // Invalid edgeit is always forward :)
348 if( e.it == edges.end() ) {
353 e.forw = ( G.tail(*e.it) == common_node );
357 template<typename Gr>
358 typename DynamicPath<Gr>::NodeIt& DynamicPath<Gr>::next(NodeIt &n) const {
359 if( n.idx >= length() ) {
366 GraphNode next_node = ( n.tail ? G.head(edges[n.idx]) :
367 G.tail(edges[n.idx]) );
369 if( n.idx < length() ) {
370 n.tail = ( next_node == G.tail(edges[n.idx]) );
379 template<typename Gr>
380 bool DynamicPath<Gr>::edgeIncident(const GraphEdge &e, const GraphNode &a,
382 if( G.tail(e) == a ) {
386 if( G.head(e) == a ) {
393 template<typename Gr>
394 bool DynamicPath<Gr>::connectTwoEdges(const GraphEdge &e,
395 const GraphEdge &f) {
396 if( edgeIncident(f, G.tail(e), _last) ) {
400 if( edgeIncident(f, G.head(e), _last) ) {
407 template<typename Gr>
408 bool DynamicPath<Gr>::pushFront(const GraphEdge &e) {
409 if( G.valid(_first) ) {
410 if( edgeIncident(e, _first, _first) ) {
417 else if( length() < 1 || connectTwoEdges(e, edges[0]) ) {
425 template<typename Gr>
426 bool DynamicPath<Gr>::pushBack(const GraphEdge &e) {
427 if( G.valid(_last) ) {
428 if( edgeIncident(e, _last, _last) ) {
435 else if( length() < 1 || connectTwoEdges(edges[0], e) ) {
444 template<typename Gr>
445 bool DynamicPath<Gr>::setFrom(const GraphNode &n) {
446 if( G.valid(_first) ) {
451 if( edgeIncident(edges[0], n, _last) ) {
464 template<typename Gr>
465 bool DynamicPath<Gr>::setTo(const GraphNode &n) {
466 if( G.valid(_last) ) {
471 if( edgeIncident(edges[0], n, _first) ) {
485 template<typename Gr>
486 typename DynamicPath<Gr>::NodeIt
487 DynamicPath<Gr>::tail(const EdgeIt& e) const {
490 if( e.it == edges.end() ) {
491 // FIXME: invalid-> invalid
492 n.idx = length() + 1;
497 n.idx = e.it-edges.begin();
502 template<typename Gr>
503 typename DynamicPath<Gr>::NodeIt
504 DynamicPath<Gr>::head(const EdgeIt& e) const {
505 if( e.it == edges.end()-1 ) {
509 EdgeIt next_edge = e;
511 return tail(next_edge);
514 template<typename Gr>
515 typename DynamicPath<Gr>::GraphEdge
516 DynamicPath<Gr>::graphEdge(const EdgeIt& e) const {
517 if( e.it != edges.end() ) {
525 template<typename Gr>
526 typename DynamicPath<Gr>::GraphNode
527 DynamicPath<Gr>::graphNode(const NodeIt& n) const {
528 if( n.idx < length() ) {
529 return n.tail ? G.tail(edges[n.idx]) : G.head(edges[n.idx]);
531 else if( n.idx == length() ) {
539 template<typename Gr>
540 typename DynamicPath<Gr>::EdgeIt&
541 DynamicPath<Gr>::nth(EdgeIt &e, size_t k) const {
542 if( k<0 || k>=length() ) {
543 // FIXME: invalid EdgeIt
549 e.it = edges.begin()+k;
551 e.forw = ( G.tail(*e.it) == _first );
554 e.forw = ( G.tail(*e.it) == G.tail(edges[k-1]) ||
555 G.tail(*e.it) == G.head(edges[k-1]) );
560 template<typename Gr>
561 typename DynamicPath<Gr>::NodeIt&
562 DynamicPath<Gr>::nth(NodeIt &n, size_t k) const {
563 if( k<0 || k>length() ) {
564 // FIXME: invalid NodeIt
574 n = tail(nth<EdgeIt>(k));
578 // Reszut konstruktorok:
581 template<typename Gr>
582 DynamicPath<Gr>::DynamicPath(const DynamicPath &P, const EdgeIt &a,
584 G(P.G), edges(a.it, b.it) // WARNING: if b.it < a.it this will blow up!
586 if( G.valid(P._first) && a.it < P.edges.end() ) {
587 _first = ( a.forw ? G.tail(*a.it) : G.head(*a.it) );
588 if( b.it < P.edges.end() ) {
589 _last = ( b.forw ? G.tail(*b.it) : G.head(*b.it) );
597 template<typename Gr>
598 DynamicPath<Gr>::DynamicPath(const DynamicPath &P, const NodeIt &a,
599 const NodeIt &b) : G(P.G)
601 if( !P.valid(a) || !P.valid(b) )
604 int ai = a.idx, bi = b.idx;
609 copy(P.edges.begin()+ai, P.edges.begin()+bi, edges.begin());
611 _first = P.graphNode(a);
612 _last = P.graphNode(b);
618 #endif // HUGO_PATH_H