Changeset 2335:27aa03cd3121 in lemon-0.x for lemon/path.h
- Timestamp:
- 01/08/07 11:39:59 (17 years ago)
- Branch:
- default
- Phase:
- public
- Convert:
- svn:c9d7d8f5-90d6-0310-b91f-818b3a526b0e/lemon/trunk@3123
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
lemon/path.h
r2247 r2335 29 29 #include <algorithm> 30 30 31 #include <lemon/path_utils.h> 31 32 #include <lemon/error.h> 32 33 #include <lemon/bits/invalid.h> … … 38 39 39 40 40 //! \brief A structure for representing directed paths in a graph. 41 //! 42 //! A structure for representing directed path in a graph. 43 //! \param Graph The graph type in which the path is. 44 //! 45 //! In a sense, the path can be treated as a graph, for is has \c NodeIt 46 //! and \c EdgeIt with the same usage. These types converts to the \c Node 47 //! and \c Edge of the original graph. 48 //! 49 //! \todo Thoroughfully check all the range and consistency tests. 50 template<typename Graph> 41 /// \brief A structure for representing directed paths in a graph. 42 /// 43 /// A structure for representing directed path in a graph. 44 /// \param Graph The graph type in which the path is. 45 /// 46 /// In a sense, the path can be treated as a list of edges. The 47 /// lemon path type stores just this list. As a consequence it 48 /// cannot enumerate the nodes in the path and the zero length paths 49 /// cannot store the source. 50 /// 51 /// This implementation is a back and front insertable and erasable 52 /// path type. It can be indexed in O(1) time. The front and back 53 /// insertion and erasure is amortized O(1) time. The 54 /// impelementation is based on two opposite organized vectors. 55 template <typename _Graph> 51 56 class Path { 52 57 public: 53 /// Edge type of the underlying graph. 58 59 typedef _Graph Graph; 54 60 typedef typename Graph::Edge Edge; 55 /// Node type of the underlying graph. 56 typedef typename Graph::Node Node; 57 58 class NodeIt; 59 class EdgeIt; 60 61 struct PathError : public LogicError { 62 virtual const char* what() const throw() { 63 return "lemon::PathError"; 64 } 65 }; 66 67 public: 68 69 /// \brief Constructor 70 /// 71 /// Constructor 72 /// \param _G The graph in which the path is. 73 Path(const Graph &_graph) : graph(&_graph), start(INVALID) {} 74 75 /// \brief Subpath constructor. 76 /// 77 /// Subpath defined by two nodes. 78 /// \warning It is an error if the two edges are not in order! 79 Path(const Path &other, const NodeIt &a, const NodeIt &b) { 80 graph = other.graph; 81 start = a; 82 edges.insert(edges.end(), 83 other.edges.begin() + a.id, other.edges.begin() + b.id); 84 } 85 86 /// \brief Subpath constructor. 87 /// 88 /// Subpath defined by two edges. Contains edges in [a,b) 89 /// \warning It is an error if the two edges are not in order! 90 Path(const Path &other, const EdgeIt &a, const EdgeIt &b) { 91 graph = other.graph; 92 start = graph->source(a); 93 edges.insert(edges.end(), 94 other.edges.begin() + a.id, other.edges.begin() + b.id); 95 } 96 97 /// \brief Length of the path. 98 /// 99 /// The number of the edges in the path. It can be zero if the 100 /// path has only one node or it is empty. 101 int length() const { return edges.size(); } 102 103 /// \brief Returns whether the path is empty. 104 /// 105 /// Returns true when the path does not contain neither edge nor 106 /// node. 107 bool empty() const { return start == INVALID; } 108 109 /// \brief Resets the path to an empty path. 110 /// 111 /// Resets the path to an empty path. 112 void clear() { edges.clear(); start = INVALID; } 113 114 /// \brief Starting point of the path. 115 /// 116 /// Starting point of the path. 117 /// Returns INVALID if the path is empty. 118 Node source() const { 119 return start; 120 } 121 /// \brief End point of the path. 122 /// 123 /// End point of the path. 124 /// Returns INVALID if the path is empty. 125 Node target() const { 126 return length() == 0 ? start : graph->target(edges[length()-1]); 127 } 128 129 /// \brief Gives back a node iterator to point to the node of a 130 /// given index. 131 /// 132 /// Gives back a node iterator to point to the node of a given 133 /// index. 134 /// \pre n should less or equal to \c length() 135 NodeIt nthNode(int n) const { 136 return NodeIt(*this, n); 137 } 138 139 /// \brief Gives back an edge iterator to point to the edge of a 140 /// given index. 141 /// 142 /// Gives back an edge iterator to point to the node of a given 143 /// index. 144 /// \pre n should less than \c length() 145 EdgeIt nthEdge(int n) const { 146 return EdgeIt(*this, n); 147 } 148 149 /// \brief Returns node iterator pointing to the source node of the 150 /// given edge iterator. 151 /// 152 /// Returns node iterator pointing to the source node of the given 153 /// edge iterator. 154 NodeIt source(const EdgeIt& e) const { 155 return NodeIt(*this, e.id); 156 } 157 158 /// \brief Returns node iterator pointing to the target node of the 159 /// given edge iterator. 160 /// 161 /// Returns node iterator pointing to the target node of the given 162 /// edge iterator. 163 NodeIt target(const EdgeIt& e) const { 164 return NodeIt(*this, e.id + 1); 165 } 166 167 168 /// \brief Iterator class to iterate on the nodes of the paths 169 /// 170 /// This class is used to iterate on the nodes of the paths 171 /// 172 /// Of course it converts to Graph::Node 173 class NodeIt { 174 friend class Path; 175 public: 176 177 /// \brief Default constructor 178 /// 179 /// Default constructor 180 NodeIt() {} 181 182 /// \brief Invalid constructor 183 /// 184 /// Invalid constructor 185 NodeIt(Invalid) : id(-1), path(0) {} 186 187 /// \brief Constructor with starting point 188 /// 189 /// Constructor with starting point 190 NodeIt(const Path &_path, int _id = 0) : id(_id), path(&_path) { 191 if (id > path->length()) id = -1; 192 } 193 194 /// \brief Conversion to Graph::Node 195 /// 196 /// Conversion to Graph::Node 197 operator Node() const { 198 if (id > 0) { 199 return path->graph->target(path->edges[id - 1]); 200 } else if (id == 0) { 201 return path->start; 202 } else { 203 return INVALID; 204 } 205 } 206 207 /// \brief Steps to the next node 208 /// 209 /// Steps to the next node 210 NodeIt& operator++() { 211 ++id; 212 if (id > path->length()) id = -1; 213 return *this; 214 } 215 216 /// \brief Comparison operator 217 /// 218 /// Comparison operator 219 bool operator==(const NodeIt& n) const { return id == n.id; } 220 221 /// \brief Comparison operator 222 /// 223 /// Comparison operator 224 bool operator!=(const NodeIt& n) const { return id != n.id; } 225 226 /// \brief Comparison operator 227 /// 228 /// Comparison operator 229 bool operator<(const NodeIt& n) const { return id < n.id; } 230 231 private: 232 int id; 233 const Path *path; 234 }; 235 236 /// \brief Iterator class to iterate on the edges of the paths 237 /// 238 /// This class is used to iterate on the edges of the paths 239 /// Of course it converts to Graph::Edge 61 62 /// \brief Default constructor 63 /// 64 /// Default constructor 65 Path() {} 66 67 /// \brief Template copy constructor 68 /// 69 /// This path can be initialized with any other path type. It just 70 /// makes a copy of the given path. 71 template <typename CPath> 72 Path(const CPath& cpath) { 73 copyPath(*this, cpath); 74 } 75 76 /// \brief Template copy assignment 77 /// 78 /// This path can be initialized with any other path type. It just 79 /// makes a copy of the given path. 80 template <typename CPath> 81 Path& operator=(const CPath& cpath) { 82 copyPath(*this, cpath); 83 return *this; 84 } 85 86 /// \brief Lemon style iterator for path edges 87 /// 88 /// This class is used to iterate on the edges of the paths. 240 89 class EdgeIt { 241 90 friend class Path; 242 91 public: 243 244 92 /// \brief Default constructor 245 /// 93 EdgeIt() {} 94 /// \brief Invalid constructor 95 EdgeIt(Invalid) : path(0), idx(-1) {} 96 /// \brief Initializate the constructor to the first edge of path 97 EdgeIt(const Path &_path) 98 : path(&_path), idx(_path.empty() ? -1 : 0) {} 99 100 private: 101 102 EdgeIt(const Path &_path, int _idx) 103 : idx(_idx), path(&_path) {} 104 105 public: 106 107 /// \brief Conversion to Edge 108 operator const Edge&() const { 109 return path->nth(idx); 110 } 111 112 /// \brief Next edge 113 EdgeIt& operator++() { 114 ++idx; 115 if (idx >= path->length()) idx = -1; 116 return *this; 117 } 118 119 /// \brief Comparison operator 120 bool operator==(const EdgeIt& e) const { return idx==e.idx; } 121 /// \brief Comparison operator 122 bool operator!=(const EdgeIt& e) const { return idx!=e.idx; } 123 /// \brief Comparison operator 124 bool operator<(const EdgeIt& e) const { return idx<e.idx; } 125 126 private: 127 const Path *path; 128 int idx; 129 }; 130 131 /// \brief Length of the path. 132 int length() const { return head.size() + tail.size(); } 133 /// \brief Returns whether the path is empty. 134 bool empty() const { return head.empty() && tail.empty(); } 135 136 /// \brief Resets the path to an empty path. 137 void clear() { head.clear(); tail.clear(); } 138 139 /// \brief Gives back the nth edge. 140 /// 141 /// \pre n is in the [0..length() - 1] range 142 const Edge& nth(int n) const { 143 return n < (int)head.size() ? *(head.rbegin() + n) : 144 *(tail.begin() + (n - head.size())); 145 } 146 147 /// \brief Initializes edge iterator to point to the nth edge 148 /// 149 /// \pre n is in the [0..length() - 1] range 150 EdgeIt nthIt(int n) const { 151 return EdgeIt(*this, n); 152 } 153 154 /// \brief Gives back the first edge of the path 155 const Edge& front() const { 156 return head.empty() ? tail.front() : head.back(); 157 } 158 159 /// \brief Add a new edge before the current path 160 void addFront(const Edge& edge) { 161 head.push_back(edge); 162 } 163 164 /// \brief Erase the first edge of the path 165 void eraseFront() { 166 if (!head.empty()) { 167 head.pop_back(); 168 } else { 169 head.clear(); 170 int halfsize = tail.size() / 2; 171 head.resize(halfsize); 172 std::copy(tail.begin() + 1, tail.begin() + halfsize + 1, 173 head.rbegin()); 174 std::copy(tail.begin() + halfsize + 1, tail.end(), tail.begin()); 175 tail.resize(tail.size() - halfsize - 1); 176 } 177 } 178 179 /// \brief Gives back the last edge of the path 180 const Edge& back() const { 181 return tail.empty() ? head.front() : tail.back(); 182 } 183 184 /// \brief Add a new edge behind the current path 185 void addBack(const Edge& edge) { 186 tail.push_back(edge); 187 } 188 189 /// \brief Erase the last edge of the path 190 void eraseBack() { 191 if (!tail.empty()) { 192 tail.pop_back(); 193 } else { 194 int halfsize = head.size() / 2; 195 tail.resize(halfsize); 196 std::copy(head.begin() + 1, head.begin() + halfsize + 1, 197 tail.rbegin()); 198 std::copy(head.begin() + halfsize + 1, head.end(), head.begin()); 199 head.resize(head.size() - halfsize - 1); 200 } 201 } 202 203 204 205 typedef True BuildTag; 206 207 template <typename CPath> 208 void build(const CPath& path) { 209 int len = path.length(); 210 tail.reserve(len); 211 for (typename CPath::EdgeIt it(path); it != INVALID; ++it) { 212 tail.push_back(it); 213 } 214 } 215 216 template <typename CPath> 217 void buildRev(const CPath& path) { 218 int len = path.length(); 219 head.reserve(len); 220 for (typename CPath::RevIt it(path); it != INVALID; ++it) { 221 head.push_back(it); 222 } 223 } 224 225 protected: 226 typedef std::vector<Edge> Container; 227 Container head, tail; 228 229 }; 230 231 /// \brief A structure for representing directed paths in a graph. 232 /// 233 /// A structure for representing directed path in a graph. 234 /// \param Graph The graph type in which the path is. 235 /// 236 /// In a sense, the path can be treated as a list of edges. The 237 /// lemon path type stores just this list. As a consequence it 238 /// cannot enumerate the nodes in the path and the zero length paths 239 /// cannot store the source. 240 /// 241 /// This implementation is a just back insertable and erasable path 242 /// type. It can be indexed in O(1) time. The back insertion and 243 /// erasure is amortized O(1) time. This implementation is faster 244 /// then the \c Path type because it use just one vector for the 245 /// edges. 246 template <typename _Graph> 247 class SimplePath { 248 public: 249 250 typedef _Graph Graph; 251 typedef typename Graph::Edge Edge; 252 253 /// \brief Default constructor 254 /// 255 /// Default constructor 256 SimplePath() {} 257 258 /// \brief Template copy constructor 259 /// 260 /// This path can be initialized with any other path type. It just 261 /// makes a copy of the given path. 262 template <typename CPath> 263 SimplePath(const CPath& cpath) { 264 copyPath(*this, cpath); 265 } 266 267 /// \brief Template copy assignment 268 /// 269 /// This path can be initialized with any other path type. It just 270 /// makes a copy of the given path. 271 template <typename CPath> 272 SimplePath& operator=(const CPath& cpath) { 273 copyPath(*this, cpath); 274 return *this; 275 } 276 277 /// \brief Iterator class to iterate on the edges of the paths 278 /// 279 /// This class is used to iterate on the edges of the paths 280 /// 281 /// Of course it converts to Graph::Edge 282 class EdgeIt { 283 friend class SimplePath; 284 public: 246 285 /// Default constructor 247 286 EdgeIt() {} 248 249 /// \brief Invalid constructor250 ///251 287 /// Invalid constructor 252 EdgeIt(Invalid) : id(-1), path(0) {} 253 254 /// \brief Constructor with starting point 255 /// 288 EdgeIt(Invalid) : path(0), idx(-1) {} 289 /// \brief Initializate the constructor to the first edge of path 290 EdgeIt(const SimplePath &_path) 291 : path(&_path), idx(_path.empty() ? -1 : 0) {} 292 293 private: 294 256 295 /// Constructor with starting point 257 EdgeIt(const Path &_path, int _id = 0) : id(_id), path(&_path) { 258 if (id >= path->length()) id = -1; 259 } 260 261 /// \brief Conversion to Graph::Edge 262 /// 263 /// Conversion to Graph::Edge 264 operator Edge() const { 265 return id != -1 ? path->edges[id] : INVALID; 266 } 267 268 /// \brief Steps to the next edge 269 /// 270 /// Steps to the next edge 296 EdgeIt(const SimplePath &_path, int _idx) 297 : idx(_idx), path(&_path) {} 298 299 public: 300 301 ///Conversion to Graph::Edge 302 operator const Edge&() const { 303 return path->nth(idx); 304 } 305 306 /// Next edge 271 307 EdgeIt& operator++() { 272 ++id ;273 if (id >= path->length()) id = -1;308 ++idx; 309 if (idx >= path->length()) idx = -1; 274 310 return *this; 275 311 } 276 312 277 /// \brief Comparison operator278 ///279 313 /// Comparison operator 280 bool operator==(const EdgeIt& e) const { return id == e.id; } 281 282 /// \brief Comparison operator 283 /// 314 bool operator==(const EdgeIt& e) const { return idx==e.idx; } 284 315 /// Comparison operator 285 bool operator!=(const EdgeIt& e) const { return id != e.id; } 286 287 /// \brief Comparison operator 288 /// 316 bool operator!=(const EdgeIt& e) const { return idx!=e.idx; } 289 317 /// Comparison operator 290 bool operator<(const EdgeIt& e) const { return id < e.id; }318 bool operator<(const EdgeIt& e) const { return idx<e.idx; } 291 319 292 320 private: 293 294 int id; 295 const Path *path; 321 const SimplePath *path; 322 int idx; 296 323 }; 297 324 325 /// \brief Length of the path. 326 int length() const { return data.size(); } 327 /// \brief Returns whether the path is empty. 328 bool empty() const { return data.empty(); } 329 330 /// \brief Resets the path to an empty path. 331 void clear() { data.clear(); } 332 333 /// \brief Gives back the nth edge. 334 /// 335 /// \pre n is in the [0..length() - 1] range 336 const Edge& nth(int n) const { 337 return data[n]; 338 } 339 340 /// \brief Initializes edge iterator to point to the nth edge. 341 EdgeIt nthIt(int n) const { 342 return EdgeIt(*this, n); 343 } 344 345 /// \brief Gives back the last edge of the path. 346 const Edge& back() const { 347 return data.back(); 348 } 349 350 /// \brief Add a new edge behind the current path. 351 void addBack(const Edge& edge) { 352 data.push_back(edge); 353 } 354 355 /// \brief Erase the last edge of the path 356 void eraseBack() { 357 data.pop_back(); 358 } 359 360 typedef True BuildTag; 361 362 template <typename CPath> 363 void build(const CPath& path) { 364 int len = path.length(); 365 data.resize(len); 366 int index = 0; 367 for (typename CPath::EdgeIt it(path); it != INVALID; ++it) { 368 data[index] = it;; 369 ++index; 370 } 371 } 372 373 template <typename CPath> 374 void buildRev(const CPath& path) { 375 int len = path.length(); 376 data.resize(len); 377 int index = len; 378 for (typename CPath::RevIt it(path); it != INVALID; ++it) { 379 --index; 380 data[index] = it;; 381 } 382 } 383 298 384 protected: 299 300 const Graph *graph;301 302 385 typedef std::vector<Edge> Container; 303 Container edges; 304 Node start; 305 386 Container data; 387 388 }; 389 390 /// \brief A structure for representing directed paths in a graph. 391 /// 392 /// A structure for representing directed path in a graph. 393 /// \param Graph The graph type in which the path is. 394 /// 395 /// In a sense, the path can be treated as a list of edges. The 396 /// lemon path type stores just this list. As a consequence it 397 /// cannot enumerate the nodes in the path and the zero length paths 398 /// cannot store the source. 399 /// 400 /// This implementation is a back and front insertable and erasable 401 /// path type. It can be indexed in O(k) time, where k is the rank 402 /// of the edge in the path. The length can be computed in O(n) 403 /// time. The front and back insertion and erasure is O(1) time 404 /// and it can be splited and spliced in O(1) time. 405 template <typename _Graph> 406 class ListPath { 306 407 public: 307 408 308 friend class Builder; 309 310 /// \brief Class to build paths 311 /// 312 /// This class is used to fill a path with edges. 313 /// 314 /// You can push new edges to the front and to the back of the 315 /// path in arbitrary order then you should commit these changes 316 /// to the graph. 317 /// 318 /// Fundamentally, for most "Paths" (classes fulfilling the 319 /// PathConcept) while the builder is active (after the first 320 /// modifying operation and until the commit()) the original Path 321 /// is in a "transitional" state (operations on it have undefined 322 /// result). But in the case of Path the original path remains 323 /// unchanged until the commit. However we don't recomend that you 324 /// use this feature. 325 class Builder { 409 typedef _Graph Graph; 410 typedef typename Graph::Edge Edge; 411 412 protected: 413 414 // the std::list<> is incompatible 415 // hard to create invalid iterator 416 struct Node { 417 Edge edge; 418 Node *next, *prev; 419 }; 420 421 Node *first, *last; 422 423 std::allocator<Node> alloc; 424 425 public: 426 427 /// \brief Default constructor 428 /// 429 /// Default constructor 430 ListPath() : first(0), last(0) {} 431 432 /// \brief Template copy constructor 433 /// 434 /// This path can be initialized with any other path type. It just 435 /// makes a copy of the given path. 436 template <typename CPath> 437 ListPath(const CPath& cpath) : first(0), last(0) { 438 copyPath(*this, cpath); 439 } 440 441 /// \brief Destructor of the path 442 /// 443 /// Destructor of the path 444 ~ListPath() { 445 clear(); 446 } 447 448 /// \brief Template copy assignment 449 /// 450 /// This path can be initialized with any other path type. It just 451 /// makes a copy of the given path. 452 template <typename CPath> 453 ListPath& operator=(const CPath& cpath) { 454 copyPath(*this, cpath); 455 return *this; 456 } 457 458 /// \brief Iterator class to iterate on the edges of the paths 459 /// 460 /// This class is used to iterate on the edges of the paths 461 /// 462 /// Of course it converts to Graph::Edge 463 class EdgeIt { 464 friend class ListPath; 326 465 public: 327 /// \brief Constructor 328 /// 329 /// Constructor 330 /// \param _path the path you want to fill in. 331 Builder(Path &_path) : path(_path), start(INVALID) {} 332 333 /// \brief Destructor 334 /// 335 /// Destructor 336 ~Builder() { 337 LEMON_ASSERT(front.empty() && back.empty() && start == INVALID, 338 PathError()); 339 } 340 341 /// \brief Sets the starting node of the path. 342 /// 343 /// Sets the starting node of the path. Edge added to the path 344 /// afterwards have to be incident to this node. It should be 345 /// called if and only if the path is empty and before any call 346 /// to \ref pushFront() or \ref pushBack() 347 void setStartNode(const Node &_start) { 348 LEMON_ASSERT(path.empty() && start == INVALID, PathError()); 349 start = _start; 350 } 351 352 /// \brief Push a new edge to the front of the path 353 /// 354 /// Push a new edge to the front of the path. 355 /// \sa setStartNode 356 void pushFront(const Edge& e) { 357 LEMON_ASSERT(front.empty() || 358 (path.graph->source(front.back()) == 359 path.graph->target(e)), PathError()); 360 LEMON_ASSERT(path.empty() || 361 (path.source() == path.graph->target(e)), PathError()); 362 LEMON_ASSERT(!path.empty() || !front.empty() || 363 (start == path.graph->target(e)), PathError()); 364 front.push_back(e); 365 } 366 367 /// \brief Push a new edge to the back of the path 368 /// 369 /// Push a new edge to the back of the path. 370 /// \sa setStartNode 371 void pushBack(const Edge& e) { 372 LEMON_ASSERT(back.empty() || 373 (path.graph->target(back.back()) == 374 path.graph->source(e)), PathError()); 375 LEMON_ASSERT(path.empty() || 376 (path.target() == path.graph->source(e)), PathError()); 377 LEMON_ASSERT(!path.empty() || !back.empty() || 378 (start == path.graph->source(e)), PathError()); 379 back.push_back(e); 380 } 381 382 /// \brief Commit the changes to the path. 383 /// 384 /// Commit the changes to the path. 385 void commit() { 386 if( !front.empty() || !back.empty() || start != INVALID) { 387 Container tmp; 388 tmp.reserve(front.size() + back.size() + path.length()); 389 tmp.insert(tmp.end(), front.rbegin(), front.rend()); 390 tmp.insert(tmp.end(), path.edges.begin(), path.edges.end()); 391 tmp.insert(tmp.end(), back.begin(), back.end()); 392 path.edges.swap(tmp); 393 if (!front.empty()) { 394 path.start = path.graph->source(front.back()); 466 /// Default constructor 467 EdgeIt() {} 468 /// Invalid constructor 469 EdgeIt(Invalid) : path(0), node(0) {} 470 /// \brief Initializate the constructor to the first edge of path 471 EdgeIt(const ListPath &_path) 472 : path(&_path), node(_path.first) {} 473 474 protected: 475 476 EdgeIt(const ListPath &_path, Node *_node) 477 : path(&_path), node(_node) {} 478 479 480 public: 481 482 ///Conversion to Graph::Edge 483 operator const Edge&() const { 484 return node->edge; 485 } 486 487 /// Next edge 488 EdgeIt& operator++() { 489 node = node->next; 490 return *this; 491 } 492 493 /// Comparison operator 494 bool operator==(const EdgeIt& e) const { return node==e.node; } 495 /// Comparison operator 496 bool operator!=(const EdgeIt& e) const { return node!=e.node; } 497 /// Comparison operator 498 bool operator<(const EdgeIt& e) const { return node<e.node; } 499 500 private: 501 const ListPath *path; 502 Node *node; 503 }; 504 505 /// \brief Gives back the nth edge. 506 /// 507 /// Gives back the nth edge in O(n) time. 508 /// \pre n is in the [0..length() - 1] range 509 const Edge& nth(int n) const { 510 Node *node = first; 511 for (int i = 0; i < n; ++i) { 512 node = node->next; 513 } 514 return node->edge; 515 } 516 517 /// \brief Initializes edge iterator to point to the nth edge. 518 EdgeIt nthIt(int n) const { 519 Node *node = first; 520 for (int i = 0; i < n; ++i) { 521 node = node->next; 522 } 523 return EdgeIt(*this, node); 524 } 525 526 /// \brief Length of the path. 527 int length() const { 528 int len = 0; 529 Node *node = first; 530 while (node != 0) { 531 node = node->next; 532 ++len; 533 } 534 return len; 535 } 536 537 /// \brief Returns whether the path is empty. 538 bool empty() const { return first == 0; } 539 540 /// \brief Resets the path to an empty path. 541 void clear() { 542 while (first != 0) { 543 last = first->next; 544 alloc.destroy(first); 545 alloc.deallocate(first, 1); 546 first = last; 547 } 548 } 549 550 /// \brief Gives back the first edge of the path 551 const Edge& front() const { 552 return first->edge; 553 } 554 555 /// \brief Add a new edge before the current path 556 void addFront(const Edge& edge) { 557 Node *node = alloc.allocate(1); 558 alloc.construct(node, Node()); 559 node->prev = 0; 560 node->next = first; 561 node->edge = edge; 562 if (first) { 563 first->prev = node; 564 first = node; 565 } else { 566 first = last = node; 567 } 568 } 569 570 /// \brief Erase the first edge of the path 571 void eraseFront() { 572 Node *node = first; 573 first = first->next; 574 if (first) { 575 first->prev = 0; 576 } else { 577 last = 0; 578 } 579 alloc.destroy(node); 580 alloc.deallocate(node, 1); 581 } 582 583 /// \brief Gives back the last edge of the path. 584 const Edge& back() const { 585 return last->edge; 586 } 587 588 /// \brief Add a new edge behind the current path. 589 void addBack(const Edge& edge) { 590 Node *node = alloc.allocate(1); 591 alloc.construct(node, Node()); 592 node->next = 0; 593 node->prev = last; 594 node->edge = edge; 595 if (last) { 596 last->next = node; 597 last = node; 598 } else { 599 last = first = node; 600 } 601 } 602 603 /// \brief Erase the last edge of the path 604 void eraseBack() { 605 Node *node = last; 606 last = last->prev; 607 if (last) { 608 last->next = 0; 609 } else { 610 first = 0; 611 } 612 alloc.destroy(node); 613 alloc.deallocate(node, 1); 614 } 615 616 /// \brief Splicing the given path to the current path. 617 /// 618 /// It splices the \c tpath to the back of the current path and \c 619 /// tpath becomes empty. The time complexity of this function is 620 /// O(1). 621 void spliceBack(ListPath& tpath) { 622 if (first) { 623 if (tpath.first) { 624 last->next = tpath.first; 625 tpath.first->prev = last; 626 last = tpath.last; 627 } 628 } else { 629 first = tpath.first; 630 last = tpath.last; 631 } 632 tpath.first = tpath.last = 0; 633 } 634 635 /// \brief Splicing the given path to the current path. 636 /// 637 /// It splices the \c tpath before the current path and \c tpath 638 /// becomes empty. The time complexity of this function 639 /// is O(1). 640 void spliceFront(ListPath& tpath) { 641 if (first) { 642 if (tpath.first) { 643 first->prev = tpath.last; 644 tpath.last->next = first; 645 first = tpath.first; 646 } 647 } else { 648 first = tpath.first; 649 last = tpath.last; 650 } 651 tpath.first = tpath.last = 0; 652 } 653 654 /// \brief Splicing the given path into the current path. 655 /// 656 /// It splices the \c tpath into the current path before the 657 /// position of \c it iterator and \c tpath becomes empty. The 658 /// time complexity of this function is O(1). If the \c it is \c 659 /// INVALID then it will splice behind the current path. 660 void splice(EdgeIt it, ListPath& tpath) { 661 if (it.node) { 662 if (tpath.first) { 663 tpath.first->prev = it.node->prev; 664 if (it.node->prev) { 665 it.node->prev->next = tpath.first; 395 666 } else { 396 path.start = start;667 first = tpath.first; 397 668 } 398 start = INVALID; 399 front.clear(); 400 back.clear(); 401 } 402 } 403 404 /// \brief Reserve storage for the builder in advance. 405 /// 406 /// If you know a reasonable upper bound of the number of the 407 /// edges to add to the front, using this function you can speed 408 /// up the building. 409 void reserveFront(size_t r) {front.reserve(r);} 410 411 /// \brief Reserve storage for the builder in advance. 412 /// 413 /// If you know a reasonable upper bound of the number of the 414 /// edges to add to the back, using this function you can speed 415 /// up the building. 416 void reserveBack(size_t r) {back.reserve(r);} 669 it.node->prev = tpath.last; 670 tpath.last->next = it.node; 671 } 672 } else { 673 if (first) { 674 if (tpath.first) { 675 last->next = tpath.first; 676 tpath.first->prev = last; 677 last = tpath.last; 678 } 679 } else { 680 first = tpath.first; 681 last = tpath.last; 682 } 683 } 684 tpath.first = tpath.last = 0; 685 } 686 687 /// \brief Spliting the current path. 688 /// 689 /// It splits the current path into two parts. The part before \c 690 /// it iterator will remain in the current path and the part from 691 /// the it will put into the \c tpath. If the \c tpath had edges 692 /// before the operation they will be removed first. The time 693 /// complexity of this function is O(1) plus the clearing of \c 694 /// tpath. If the \c it is \c INVALID then it just clears \c 695 /// tpath. 696 void split(EdgeIt it, ListPath& tpath) { 697 tpath.clear(); 698 if (it.node) { 699 tpath.first = it.node; 700 tpath.last = last; 701 if (it.node->prev) { 702 last = it.node->prev; 703 last->next = 0; 704 } else { 705 first = last = 0; 706 } 707 it.node->prev = 0; 708 } 709 } 710 711 712 typedef True BuildTag; 713 714 template <typename CPath> 715 void build(const CPath& path) { 716 for (typename CPath::EdgeIt it(path); it != INVALID; ++it) { 717 addBack(it); 718 } 719 } 720 721 template <typename CPath> 722 void buildRev(const CPath& path) { 723 for (typename CPath::RevIt it(path); it != INVALID; ++it) { 724 addFront(it); 725 } 726 } 727 728 }; 729 730 /// \brief A structure for representing directed paths in a graph. 731 /// 732 /// A structure for representing directed path in a graph. 733 /// \param Graph The graph type in which the path is. 734 /// 735 /// In a sense, the path can be treated as a list of edges. The 736 /// lemon path type stores just this list. As a consequence it 737 /// cannot enumerate the nodes in the path and the zero length paths 738 /// cannot store the source. 739 /// 740 /// This implementation is completly static, so it cannot be 741 /// modified exclude the assign an other path. It is intented to be 742 /// used when you want to store a large amount paths because it is 743 /// the most memory efficient path type in the lemon. 744 template <typename _Graph> 745 class StaticPath { 746 public: 747 748 typedef _Graph Graph; 749 typedef typename Graph::Edge Edge; 750 751 /// \brief Default constructor 752 /// 753 /// Default constructor 754 StaticPath() : len(0), edges(0) {} 755 756 /// \brief Template copy constructor 757 /// 758 /// This path can be initialized with any other path type. It just 759 /// makes a copy of the given path. 760 template <typename CPath> 761 StaticPath(const CPath& cpath) : edges(0) { 762 copyPath(*this, cpath); 763 } 764 765 /// \brief Destructor of the path 766 /// 767 /// Destructor of the path 768 ~StaticPath() { 769 if (edges) delete[] edges; 770 } 771 772 /// \brief Template copy assignment 773 /// 774 /// This path can be initialized with any other path type. It just 775 /// makes a copy of the given path. 776 template <typename CPath> 777 StaticPath& operator=(const CPath& cpath) { 778 copyPath(*this, cpath); 779 return *this; 780 } 781 782 /// \brief Iterator class to iterate on the edges of the paths 783 /// 784 /// This class is used to iterate on the edges of the paths 785 /// 786 /// Of course it converts to Graph::Edge 787 class EdgeIt { 788 friend class StaticPath; 789 public: 790 /// Default constructor 791 EdgeIt() {} 792 /// Invalid constructor 793 EdgeIt(Invalid) : path(0), idx(-1) {} 794 /// Initializate the constructor to the first edge of path 795 EdgeIt(const StaticPath &_path) 796 : path(&_path), idx(_path.empty() ? -1 : 0) {} 417 797 418 798 private: 419 799 420 Path &path; 421 Container front, back; 422 Node start; 423 800 /// Constructor with starting point 801 EdgeIt(const StaticPath &_path, int _idx) 802 : idx(_idx), path(&_path) {} 803 804 public: 805 806 ///Conversion to Graph::Edge 807 operator const Edge&() const { 808 return path->nth(idx); 809 } 810 811 /// Next edge 812 EdgeIt& operator++() { 813 ++idx; 814 if (idx >= path->length()) idx = -1; 815 return *this; 816 } 817 818 /// Comparison operator 819 bool operator==(const EdgeIt& e) const { return idx==e.idx; } 820 /// Comparison operator 821 bool operator!=(const EdgeIt& e) const { return idx!=e.idx; } 822 /// Comparison operator 823 bool operator<(const EdgeIt& e) const { return idx<e.idx; } 824 825 private: 826 const StaticPath *path; 827 int idx; 424 828 }; 425 829 830 /// \brief Gives back the nth edge. 831 /// 832 /// \pre n is in the [0..length() - 1] range 833 const Edge& nth(int n) const { 834 return edges[n]; 835 } 836 837 /// \brief Initializes edge iterator to point to the nth edge. 838 EdgeIt nthIt(int n) const { 839 return EdgeIt(*this, n); 840 } 841 842 /// \brief Gives back the length of the path. 843 int length() const { return len; } 844 845 /// \brief Returns true when the path is empty. 846 int empty() const { return len == 0; } 847 848 /// \break Erase all edge in the graph. 849 void clear() { 850 len = 0; 851 if (edges) delete[] edges; 852 edges = 0; 853 } 854 855 /// \brief Gives back the first edge of the path. 856 const Edge& front() const { 857 return edges[0]; 858 } 859 860 /// \brief Gives back the last edge of the path. 861 const Edge& back() const { 862 return edges[len - 1]; 863 } 864 865 866 typedef True BuildTag; 867 868 template <typename CPath> 869 void build(const CPath& path) { 870 len = path.length(); 871 edges = new Edge[len]; 872 int index = 0; 873 for (typename CPath::EdgeIt it(path); it != INVALID; ++it) { 874 edges[index] = it; 875 ++index; 876 } 877 } 878 879 template <typename CPath> 880 void buildRev(const CPath& path) { 881 len = path.length(); 882 edges = new Edge[len]; 883 int index = len; 884 for (typename CPath::RevIt it(path); it != INVALID; ++it) { 885 --index; 886 edges[index] = it; 887 } 888 } 889 890 private: 891 int len; 892 Edge* edges; 426 893 }; 427 894
Note: See TracChangeset
for help on using the changeset viewer.