diff -r 5bc1c83257f8 -r b72b36a25170 src/work/klao/path.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/work/klao/path.h Sun Mar 21 16:16:08 2004 +0000 @@ -0,0 +1,383 @@ +// -*- c++ -*- // + +/** + * + * Class for representing paths in graphs. + * + */ + +#ifndef HUGO_PATH_H +#define HUGO_PATH_H + +#include + +#include + +namespace hugo { + + /* Ennek az allocatorosdinak sokkal jobban utana kene nezni a hasznalata + elott. Eleg bonyinak nez ki, ahogyan azokat az STL-ben hasznaljak. */ + + template + class Path { + + public: + typedef typename Graph::Edge GraphEdge; + typedef typename Graph::Node GraphNode; + class NodeIt; + class EdgeIt; + + protected: + Graph& G; + // FIXME: ehelyett eleg lenne tarolni ket boolt: a ket szelso el + // iranyitasat: + GraphNode _first, _last; + typedef std::deque Container; + Container edges; + + public: + + Path(Graph &_G) : G(_G), _first(INVALID), _last(INVALID) {} + + /// Subpath defined by two nodes + Path(Path const& P, NodeIt a, NodeIt b) { FIXME; } + /// Subpath defined by tow edges. Contains edges in [a,b) + Path(Path const& P, EdgeIt a, EdgeIt b) { FIXME; } + + size_t length() const { return edges.size(); } + GraphNode from() const { return _first; } + GraphNode to() const { return _last; } + + NodeIt& first(NodeIt &n) const { return nth(n, 0); } + EdgeIt& first(EdgeIt &e) const { return nth(e, 0); } + template + It first() const { + It e; + first(e); + return e; + } + + NodeIt& nth(NodeIt &, size_t) const; + EdgeIt& nth(EdgeIt &, size_t) const; + template + It nth(size_t n) const { + It e; + nth(e, n); + return e; + } + + bool valid(const NodeIt &n) const { return n.idx <= length(); } + bool valid(const EdgeIt &e) const { return e.it < edges.end(); } + + bool isForward(const EdgeIt &e) const { return e.forw; } + + EdgeIt& next(EdgeIt &e) const; + NodeIt& next(NodeIt &n) const; + template + It getNext(It it) const { + It tmp(it); return next(tmp); + } + + // A path is constructed using the following four functions. + // They return false if the requested operation is inconsistent + // with the path constructed so far. + // If your path has only one edge you MUST set either "from" or "to"! + // So you probably SHOULD call it in any case to be safe (and check the + // returned value to check if your path is consistent with your idea). + bool pushFront(const GraphEdge &e); + bool pushBack(const GraphEdge &e); + bool setFrom(const GraphNode &n); + bool setTo(const GraphNode &n); + + // WARNING: these two functions return the head/tail of an edge with + // respect to the direction of the path! + // So G.head(P.graphEdge(e)) == P.graphNode(P.head(e)) holds only if + // P.forward(e) is true (or the edge is a loop)! + NodeIt head(const EdgeIt& e) const; + NodeIt tail(const EdgeIt& e) const; + + // FIXME: ezeknek valami jobb nev kellene!!! + GraphEdge graphEdge(const EdgeIt& e) const; + GraphNode graphNode(const NodeIt& n) const; + + + /*** Iterator classes ***/ + class EdgeIt { + friend class Path; + + typename Container::const_iterator it; + bool forw; + public: + // FIXME: jarna neki ilyen is... + // EdgeIt(Invalid); + + bool forward() const { return forw; } + + bool operator==(const EdgeIt& e) const { return it==e.it; } + bool operator!=(const EdgeIt& e) const { return it!=e.it; } + bool operator<(const EdgeIt& e) const { return it + typename Path::EdgeIt& + Path::next(Path::EdgeIt &e) const { + if( e.it == edges.end() ) + return e; + + GraphNode common_node = ( e.forw ? G.head(*e.it) : G.tail(*e.it) ); + ++e.it; + + // Invalid edgeit is always forward :) + if( e.it == edges.end() ) { + e.forw = true; + return e; + } + + e.forw = ( G.tail(*e.it) == common_node ); + return e; + } + + template + typename Path::NodeIt& Path::next(NodeIt &n) const { + if( n.idx >= length() ) { + // FIXME: invalid + n.idx = length()+1; + return n; + } + + + GraphNode next_node = ( n.tail ? G.head(edges[n.idx]) : + G.tail(edges[n.idx]) ); + ++n.idx; + if( n.idx < length() ) { + n.tail = ( next_node == G.tail(edges[n.idx]) ); + } + else { + n.tail = true; + } + + return n; + } + + template + bool Path::edgeIncident(const GraphEdge &e, const GraphNode &a, + GraphNode &b) { + if( G.tail(e) == a ) { + b=G.head(e); + return true; + } + if( G.head(e) == a ) { + b=G.tail(e); + return true; + } + return false; + } + + template + bool Path::connectTwoEdges(const GraphEdge &e, + const GraphEdge &f) { + if( edgeIncident(f, G.tail(e), _last) ) { + _first = G.head(e); + return true; + } + if( edgeIncident(f, G.head(e), _last) ) { + _first = G.tail(e); + return true; + } + return false; + } + + template + bool Path::pushFront(const GraphEdge &e) { + if( G.valid(_first) ) { + if( edgeIncident(e, _first, _first) ) { + edges.push_front(e); + return true; + } + else + return false; + } + else if( length() < 1 || connectTwoEdges(e, edges[0]) ) { + edges.push_front(e); + return true; + } + else + return false; + } + + template + bool Path::pushBack(const GraphEdge &e) { + if( G.valid(_last) ) { + if( edgeIncident(e, _last, _last) ) { + edges.push_back(e); + return true; + } + else + return false; + } + else if( length() < 1 || connectTwoEdges(edges[0], e) ) { + edges.push_back(e); + return true; + } + else + return false; + } + + + template + bool Path::setFrom(const GraphNode &n) { + if( G.valid(_first) ) { + return _first == n; + } + else { + if( length() > 0) { + if( edgeIncident(edges[0], n, _last) ) { + _first = n; + return true; + } + else return false; + } + else { + _first = _last = n; + return true; + } + } + } + + template + bool Path::setTo(const GraphNode &n) { + if( G.valid(_last) ) { + return _last == n; + } + else { + if( length() > 0) { + if( edgeIncident(edges[0], n, _first) ) { + _last = n; + return true; + } + else return false; + } + else { + _first = _last = n; + return true; + } + } + } + + + template + typename Path::NodeIt + Path::tail(const EdgeIt& e) const { + NodeIt n; + + if( e.it == edges.end() ) { + // FIXME: invalid-> invalid + n.idx = length() + 1; + n.tail = true; + return n; + } + + n.idx = e.it-edges.begin(); + n.tail = e.forw; + } + + template + typename Path::NodeIt + Path::head(const EdgeIt& e) const { + if( e.it == edges.end()-1 ) { + return _last; + } + + EdgeIt next_edge = e; + next(next_edge); + return tail(next_edge); + } + + template + typename Path::GraphEdge + Path::graphEdge(const EdgeIt& e) const { + if( e.it != edges.end() ) { + return *e.it; + } + else { + return INVALID; + } + } + + template + typename Path::GraphNode + Path::graphNode(const NodeIt& n) const { + if( n.idx < length() ) { + return n.tail ? G.tail(edges[n.idx]) : G.head(edges[n.idx]); + } + else if( n.idx == length() ) { + return _last; + } + else { + return INVALID; + } + } + + template + typename Path::EdgeIt& Path::nth(EdgeIt &e, size_t k) const { + if( k<0 || k>=length() ) { + // FIXME: invalid EdgeIt + e.it = edges.end(); + e.forw = true; + return e; + } + + e.it = edges.begin()+k; + if(k==0) { + e.forw = ( G.tail(*e.it) == _first ); + } + else { + e.forw = ( G.tail(*e.it) == G.tail(edges[k-1]) || + G.tail(*e.it) == G.head(edges[k-1]) ); + } + return e; + } + + template + typename Path::NodeIt& Path::nth(NodeIt &n, size_t k) const { + if( k<0 || k>length() ) { + // FIXME: invalid NodeIt + n.idx = length()+1; + n.tail = true; + return n; + } + if( k==length() ) { + n.idx = length(); + n.tail = true; + return n; + } + n = tail(nth(k)); + return n; + } + + +} // namespace hugo + +#endif // HUGO_PATH_H