lemon/path.h
author hegyi
Mon, 21 Nov 2005 18:03:20 +0000
changeset 1823 cb082cdf3667
parent 1435 8e85e6bbefdf
child 1875 98698b69a902
permissions -rw-r--r--
NewMapWin has become Dialog instead of Window. Therefore it is created dynamically, when there is need for it, instead of keeping one instance in memory. This solution is slower, but more correct than before.
alpar@906
     1
/* -*- C++ -*-
ladanyi@1435
     2
 * lemon/path.h - Part of LEMON, a generic C++ optimization library
alpar@906
     3
 *
alpar@1164
     4
 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@1359
     5
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
alpar@906
     6
 *
alpar@906
     7
 * Permission to use, modify and distribute this software is granted
alpar@906
     8
 * provided that this copyright notice appears in all copies. For
alpar@906
     9
 * precise terms see the accompanying LICENSE file.
alpar@906
    10
 *
alpar@906
    11
 * This software is provided "AS IS" with no warranty of any kind,
alpar@906
    12
 * express or implied, and with no claim as to its suitability for any
alpar@906
    13
 * purpose.
alpar@906
    14
 *
alpar@906
    15
 */
hegyi@819
    16
hegyi@819
    17
/**
hegyi@819
    18
@defgroup paths Path Structures
hegyi@819
    19
@ingroup datas
alpar@921
    20
\brief Path structures implemented in LEMON.
hegyi@819
    21
alpar@921
    22
LEMON provides flexible data structures
hegyi@819
    23
to work with paths.
hegyi@819
    24
hegyi@819
    25
All of them have the same interface, especially they can be built or extended
hegyi@819
    26
using a standard Builder subclass. This make is easy to have e.g. the Dijkstra
hegyi@819
    27
algorithm to store its result in any kind of path structure.
hegyi@819
    28
klao@959
    29
\sa lemon::concept::Path
hegyi@819
    30
hegyi@819
    31
*/
hegyi@819
    32
hegyi@819
    33
///\ingroup paths
hegyi@819
    34
///\file
hegyi@819
    35
///\brief Classes for representing paths in graphs.
alpar@1151
    36
///
alpar@1151
    37
///\todo Iterators have obsolete style
hegyi@819
    38
alpar@921
    39
#ifndef LEMON_PATH_H
alpar@921
    40
#define LEMON_PATH_H
hegyi@819
    41
hegyi@819
    42
#include <deque>
hegyi@819
    43
#include <vector>
hegyi@819
    44
#include <algorithm>
hegyi@819
    45
alpar@921
    46
#include <lemon/invalid.h>
hegyi@819
    47
alpar@921
    48
namespace lemon {
hegyi@819
    49
hegyi@819
    50
  /// \addtogroup paths
hegyi@819
    51
  /// @{
hegyi@819
    52
hegyi@819
    53
hegyi@819
    54
  //! \brief A structure for representing directed paths in a graph.
hegyi@819
    55
  //!
hegyi@819
    56
  //! A structure for representing directed path in a graph.
hegyi@819
    57
  //! \param Graph The graph type in which the path is.
hegyi@819
    58
  //! \param DM DebugMode, defaults to DefaultDebugMode.
hegyi@837
    59
  //!
hegyi@819
    60
  //! In a sense, the path can be treated as a graph, for is has \c NodeIt
hegyi@819
    61
  //! and \c EdgeIt with the same usage. These types converts to the \c Node
hegyi@819
    62
  //! and \c Edge of the original graph.
hegyi@819
    63
  //!
hegyi@819
    64
  //! \todo Thoroughfully check all the range and consistency tests.
hegyi@831
    65
  template<typename Graph>
hegyi@819
    66
  class DirPath {
hegyi@819
    67
  public:
hegyi@819
    68
    /// Edge type of the underlying graph.
hegyi@837
    69
    typedef typename Graph::Edge GraphEdge;
hegyi@819
    70
    /// Node type of the underlying graph.
hegyi@819
    71
    typedef typename Graph::Node GraphNode;
hegyi@819
    72
    class NodeIt;
hegyi@819
    73
    class EdgeIt;
hegyi@819
    74
hegyi@819
    75
  protected:
hegyi@819
    76
    const Graph *gr;
hegyi@819
    77
    typedef std::vector<GraphEdge> Container;
hegyi@819
    78
    Container edges;
hegyi@819
    79
hegyi@819
    80
  public:
hegyi@819
    81
hegyi@819
    82
    /// \param _G The graph in which the path is.
hegyi@819
    83
    ///
hegyi@819
    84
    DirPath(const Graph &_G) : gr(&_G) {}
hegyi@819
    85
hegyi@819
    86
    /// \brief Subpath constructor.
hegyi@819
    87
    ///
hegyi@819
    88
    /// Subpath defined by two nodes.
hegyi@819
    89
    /// \warning It is an error if the two edges are not in order!
hegyi@819
    90
    DirPath(const DirPath &P, const NodeIt &a, const NodeIt &b) {
hegyi@819
    91
      gr = P.gr;
hegyi@819
    92
      edges.insert(edges.end(), P.edges.begin()+a.idx, P.edges.begin()+b.idx);
hegyi@819
    93
    }
hegyi@819
    94
hegyi@819
    95
    /// \brief Subpath constructor.
hegyi@819
    96
    ///
hegyi@819
    97
    /// Subpath defined by two edges. Contains edges in [a,b)
hegyi@819
    98
    /// \warning It is an error if the two edges are not in order!
hegyi@819
    99
    DirPath(const DirPath &P, const EdgeIt &a, const EdgeIt &b) {
hegyi@819
   100
      gr = P.gr;
hegyi@819
   101
      edges.insert(edges.end(), P.edges.begin()+a.idx, P.edges.begin()+b.idx);
hegyi@819
   102
    }
hegyi@819
   103
hegyi@819
   104
    /// Length of the path.
alpar@1282
   105
    int length() const { return edges.size(); }
hegyi@819
   106
    /// Returns whether the path is empty.
hegyi@819
   107
    bool empty() const { return edges.empty(); }
hegyi@819
   108
hegyi@819
   109
    /// Resets the path to an empty path.
hegyi@819
   110
    void clear() { edges.clear(); }
hegyi@819
   111
hegyi@819
   112
    /// \brief Starting point of the path.
hegyi@819
   113
    ///
hegyi@819
   114
    /// Starting point of the path.
hegyi@819
   115
    /// Returns INVALID if the path is empty.
alpar@986
   116
    GraphNode source() const {
alpar@986
   117
      return empty() ? INVALID : gr->source(edges[0]);
hegyi@819
   118
    }
hegyi@819
   119
    /// \brief End point of the path.
hegyi@819
   120
    ///
hegyi@819
   121
    /// End point of the path.
hegyi@819
   122
    /// Returns INVALID if the path is empty.
alpar@986
   123
    GraphNode target() const {
alpar@986
   124
      return empty() ? INVALID : gr->target(edges[length()-1]);
hegyi@819
   125
    }
hegyi@819
   126
hegyi@819
   127
    /// \brief Initializes node or edge iterator to point to the first
hegyi@819
   128
    /// node or edge.
hegyi@819
   129
    ///
hegyi@819
   130
    /// \sa nth
hegyi@819
   131
    template<typename It>
hegyi@819
   132
    It& first(It &i) const { return i=It(*this); }
hegyi@819
   133
hegyi@819
   134
    /// \brief Initializes node iterator to point to the node of a given index.
hegyi@819
   135
    NodeIt& nth(NodeIt &i, int n) const {
hegyi@819
   136
      return i=NodeIt(*this, n);
hegyi@819
   137
    }
hegyi@819
   138
hegyi@819
   139
    /// \brief Initializes edge iterator to point to the edge of a given index.
hegyi@819
   140
    EdgeIt& nth(EdgeIt &i, int n) const {
hegyi@819
   141
      return i=EdgeIt(*this, n);
hegyi@819
   142
    }
hegyi@819
   143
alpar@986
   144
    /// \brief Returns node iterator pointing to the target node of the
hegyi@819
   145
    /// given edge iterator.
alpar@986
   146
    NodeIt target(const EdgeIt& e) const {
hegyi@819
   147
      return NodeIt(*this, e.idx+1);
hegyi@819
   148
    }
hegyi@819
   149
alpar@986
   150
    /// \brief Returns node iterator pointing to the source node of the
hegyi@819
   151
    /// given edge iterator.
alpar@986
   152
    NodeIt source(const EdgeIt& e) const {
hegyi@819
   153
      return NodeIt(*this, e.idx);
hegyi@819
   154
    }
hegyi@819
   155
hegyi@819
   156
hegyi@819
   157
    /* Iterator classes */
hegyi@819
   158
hegyi@819
   159
    /**
hegyi@819
   160
     * \brief Iterator class to iterate on the edges of the paths
hegyi@837
   161
     *
hegyi@819
   162
     * This class is used to iterate on the edges of the paths
hegyi@819
   163
     *
hegyi@819
   164
     * Of course it converts to Graph::Edge
hegyi@837
   165
     *
hegyi@819
   166
     */
hegyi@819
   167
    class EdgeIt {
hegyi@819
   168
      friend class DirPath;
hegyi@819
   169
hegyi@819
   170
      int idx;
hegyi@819
   171
      const DirPath *p;
hegyi@819
   172
    public:
hegyi@819
   173
      /// Default constructor
hegyi@819
   174
      EdgeIt() {}
hegyi@819
   175
      /// Invalid constructor
hegyi@819
   176
      EdgeIt(Invalid) : idx(-1), p(0) {}
hegyi@819
   177
      /// Constructor with starting point
hegyi@819
   178
      EdgeIt(const DirPath &_p, int _idx = 0) :
hegyi@819
   179
	idx(_idx), p(&_p) { validate(); }
hegyi@819
   180
hegyi@819
   181
      ///Validity check
hegyi@819
   182
      bool valid() const { return idx!=-1; }
hegyi@819
   183
hegyi@819
   184
      ///Conversion to Graph::Edge
hegyi@819
   185
      operator GraphEdge () const {
hegyi@819
   186
	return valid() ? p->edges[idx] : INVALID;
hegyi@819
   187
      }
hegyi@819
   188
hegyi@819
   189
      /// Next edge
hegyi@819
   190
      EdgeIt& operator++() { ++idx; validate(); return *this; }
hegyi@819
   191
hegyi@819
   192
      /// Comparison operator
hegyi@819
   193
      bool operator==(const EdgeIt& e) const { return idx==e.idx; }
hegyi@819
   194
      /// Comparison operator
hegyi@819
   195
      bool operator!=(const EdgeIt& e) const { return idx!=e.idx; }
hegyi@819
   196
      /// Comparison operator
hegyi@819
   197
      bool operator<(const EdgeIt& e) const { return idx<e.idx; }
hegyi@819
   198
hegyi@819
   199
    private:
alpar@1282
   200
      void validate() { if(idx >= p->length() ) idx=-1; }
hegyi@819
   201
    };
hegyi@819
   202
hegyi@819
   203
    /**
hegyi@819
   204
     * \brief Iterator class to iterate on the nodes of the paths
hegyi@837
   205
     *
hegyi@819
   206
     * This class is used to iterate on the nodes of the paths
hegyi@819
   207
     *
hegyi@819
   208
     * Of course it converts to Graph::Node
hegyi@837
   209
     *
hegyi@819
   210
     */
hegyi@819
   211
    class NodeIt {
hegyi@819
   212
      friend class DirPath;
hegyi@819
   213
hegyi@819
   214
      int idx;
hegyi@819
   215
      const DirPath *p;
hegyi@819
   216
    public:
hegyi@819
   217
      /// Default constructor
hegyi@819
   218
      NodeIt() {}
hegyi@819
   219
      /// Invalid constructor
hegyi@819
   220
      NodeIt(Invalid) : idx(-1), p(0) {}
hegyi@819
   221
      /// Constructor with starting point
hegyi@819
   222
      NodeIt(const DirPath &_p, int _idx = 0) :
hegyi@819
   223
	idx(_idx), p(&_p) { validate(); }
hegyi@819
   224
hegyi@819
   225
      ///Validity check
hegyi@819
   226
      bool valid() const { return idx!=-1; }
hegyi@819
   227
hegyi@819
   228
      ///Conversion to Graph::Node
hegyi@819
   229
      operator const GraphNode& () const {
hegyi@819
   230
	if(idx >= p->length())
alpar@986
   231
	  return p->target();
hegyi@819
   232
	else if(idx >= 0)
alpar@986
   233
	  return p->gr->source(p->edges[idx]);
hegyi@819
   234
	else
hegyi@819
   235
	  return INVALID;
hegyi@819
   236
      }
hegyi@819
   237
      /// Next node
hegyi@819
   238
      NodeIt& operator++() { ++idx; validate(); return *this; }
hegyi@819
   239
hegyi@819
   240
      /// Comparison operator
hegyi@819
   241
      bool operator==(const NodeIt& e) const { return idx==e.idx; }
hegyi@819
   242
      /// Comparison operator
hegyi@819
   243
      bool operator!=(const NodeIt& e) const { return idx!=e.idx; }
hegyi@819
   244
      /// Comparison operator
hegyi@819
   245
      bool operator<(const NodeIt& e) const { return idx<e.idx; }
hegyi@819
   246
hegyi@819
   247
    private:
alpar@1282
   248
      void validate() { if(idx > p->length() ) idx=-1; }
hegyi@819
   249
    };
hegyi@819
   250
hegyi@837
   251
    friend class Builder;
hegyi@819
   252
hegyi@819
   253
    /**
hegyi@819
   254
     * \brief Class to build paths
hegyi@837
   255
     *
hegyi@819
   256
     * This class is used to fill a path with edges.
hegyi@819
   257
     *
hegyi@819
   258
     * You can push new edges to the front and to the back of the path in
hegyi@819
   259
     * arbitrary order then you should commit these changes to the graph.
hegyi@819
   260
     *
hegyi@819
   261
     * Fundamentally, for most "Paths" (classes fulfilling the
hegyi@819
   262
     * PathConcept) while the builder is active (after the first modifying
hegyi@819
   263
     * operation and until the commit()) the original Path is in a
hegyi@819
   264
     * "transitional" state (operations on it have undefined result). But
hegyi@819
   265
     * in the case of DirPath the original path remains unchanged until the
hegyi@819
   266
     * commit. However we don't recomend that you use this feature.
hegyi@819
   267
     */
hegyi@819
   268
    class Builder {
hegyi@819
   269
      DirPath &P;
hegyi@819
   270
      Container front, back;
hegyi@819
   271
hegyi@819
   272
    public:
alpar@1228
   273
      ///\param _p the path you want to fill in.
hegyi@819
   274
      ///
alpar@1228
   275
      Builder(DirPath &_p) : P(_p) {}
hegyi@819
   276
hegyi@819
   277
      /// Sets the starting node of the path.
hegyi@837
   278
hegyi@819
   279
      /// Sets the starting node of the path. Edge added to the path
hegyi@819
   280
      /// afterwards have to be incident to this node.
alpar@900
   281
      /// It should be called if and only if
alpar@900
   282
      /// the path is empty and before any call to
hegyi@819
   283
      /// \ref pushFront() or \ref pushBack()
hegyi@819
   284
      void setStartNode(const GraphNode &) {}
hegyi@819
   285
hegyi@819
   286
      ///Push a new edge to the front of the path
hegyi@819
   287
hegyi@819
   288
      ///Push a new edge to the front of the path.
hegyi@819
   289
      ///\sa setStartNode
hegyi@819
   290
      void pushFront(const GraphEdge& e) {
hegyi@819
   291
	front.push_back(e);
hegyi@819
   292
      }
hegyi@819
   293
hegyi@819
   294
      ///Push a new edge to the back of the path
hegyi@819
   295
hegyi@819
   296
      ///Push a new edge to the back of the path.
hegyi@819
   297
      ///\sa setStartNode
hegyi@819
   298
      void pushBack(const GraphEdge& e) {
hegyi@819
   299
	back.push_back(e);
hegyi@819
   300
      }
hegyi@819
   301
hegyi@819
   302
      ///Commit the changes to the path.
hegyi@819
   303
      void commit() {
hegyi@837
   304
	if( !front.empty() || !back.empty() ) {
hegyi@819
   305
	  Container tmp;
hegyi@819
   306
	  tmp.reserve(front.size()+back.size()+P.length());
hegyi@819
   307
	  tmp.insert(tmp.end(), front.rbegin(), front.rend());
hegyi@819
   308
	  tmp.insert(tmp.end(), P.edges.begin(), P.edges.end());
hegyi@819
   309
	  tmp.insert(tmp.end(), back.begin(), back.end());
hegyi@819
   310
	  P.edges.swap(tmp);
hegyi@819
   311
	  front.clear();
hegyi@819
   312
	  back.clear();
hegyi@819
   313
	}
hegyi@819
   314
      }
hegyi@819
   315
hegyi@819
   316
      ///Reserve storage for the builder in advance.
hegyi@819
   317
hegyi@837
   318
      ///If you know a reasonable upper bound of the number of the edges
hegyi@837
   319
      ///to add to the front, using this function you can speed up the building.
hegyi@819
   320
hegyi@837
   321
      void reserveFront(size_t r) {front.reserve(r);}
hegyi@837
   322
hegyi@837
   323
      ///Reserve storage for the builder in advance.
hegyi@837
   324
hegyi@837
   325
      ///If you know a reasonable upper bound of the number of the edges
hegyi@837
   326
      ///to add to the back, using this function you can speed up the building.
hegyi@837
   327
hegyi@837
   328
      void reserveBack(size_t r) {back.reserve(r);}
hegyi@831
   329
hegyi@819
   330
    private:
hegyi@819
   331
      bool empty() {
hegyi@819
   332
	return front.empty() && back.empty() && P.empty();
hegyi@819
   333
      }
hegyi@819
   334
alpar@986
   335
      GraphNode source() const {
hegyi@819
   336
	if( ! front.empty() )
alpar@986
   337
	  return P.gr->source(front[front.size()-1]);
hegyi@819
   338
	else if( ! P.empty() )
alpar@986
   339
	  return P.gr->source(P.edges[0]);
hegyi@819
   340
	else if( ! back.empty() )
alpar@986
   341
	  return P.gr->source(back[0]);
hegyi@819
   342
	else
hegyi@819
   343
	  return INVALID;
hegyi@819
   344
      }
alpar@986
   345
      GraphNode target() const {
hegyi@819
   346
	if( ! back.empty() )
alpar@986
   347
	  return P.gr->target(back[back.size()-1]);
hegyi@819
   348
	else if( ! P.empty() )
alpar@986
   349
	  return P.gr->target(P.edges[P.length()-1]);
hegyi@819
   350
	else if( ! front.empty() )
alpar@986
   351
	  return P.gr->target(front[0]);
hegyi@819
   352
	else
hegyi@819
   353
	  return INVALID;
hegyi@819
   354
      }
hegyi@819
   355
hegyi@819
   356
    };
hegyi@819
   357
hegyi@819
   358
  };
hegyi@819
   359
hegyi@819
   360
hegyi@819
   361
hegyi@819
   362
hegyi@819
   363
hegyi@819
   364
hegyi@819
   365
hegyi@819
   366
hegyi@819
   367
hegyi@819
   368
hegyi@819
   369
  /**********************************************************************/
hegyi@819
   370
hegyi@819
   371
hegyi@819
   372
  //! \brief A structure for representing undirected path in a graph.
hegyi@819
   373
  //!
hegyi@819
   374
  //! A structure for representing undirected path in a graph. Ie. this is
hegyi@819
   375
  //! a path in a \e directed graph but the edges should not be directed
hegyi@819
   376
  //! forward.
hegyi@819
   377
  //!
hegyi@819
   378
  //! \param Graph The graph type in which the path is.
hegyi@819
   379
  //! \param DM DebugMode, defaults to DefaultDebugMode.
hegyi@837
   380
  //!
hegyi@819
   381
  //! In a sense, the path can be treated as a graph, for is has \c NodeIt
hegyi@819
   382
  //! and \c EdgeIt with the same usage. These types converts to the \c Node
hegyi@819
   383
  //! and \c Edge of the original graph.
hegyi@819
   384
  //!
hegyi@819
   385
  //! \todo Thoroughfully check all the range and consistency tests.
deba@1730
   386
  /// \todo May we need just path for undirected graph instead of this.
hegyi@831
   387
  template<typename Graph>
hegyi@819
   388
  class UndirPath {
hegyi@819
   389
  public:
hegyi@819
   390
    /// Edge type of the underlying graph.
hegyi@819
   391
    typedef typename Graph::Edge GraphEdge;
hegyi@819
   392
     /// Node type of the underlying graph.
hegyi@819
   393
   typedef typename Graph::Node GraphNode;
hegyi@819
   394
    class NodeIt;
hegyi@819
   395
    class EdgeIt;
hegyi@819
   396
hegyi@819
   397
  protected:
hegyi@819
   398
    const Graph *gr;
hegyi@819
   399
    typedef std::vector<GraphEdge> Container;
hegyi@819
   400
    Container edges;
hegyi@819
   401
hegyi@819
   402
  public:
hegyi@819
   403
hegyi@819
   404
    /// \param _G The graph in which the path is.
hegyi@819
   405
    ///
hegyi@819
   406
    UndirPath(const Graph &_G) : gr(&_G) {}
hegyi@819
   407
hegyi@819
   408
    /// \brief Subpath constructor.
hegyi@819
   409
    ///
hegyi@819
   410
    /// Subpath defined by two nodes.
hegyi@819
   411
    /// \warning It is an error if the two edges are not in order!
hegyi@819
   412
    UndirPath(const UndirPath &P, const NodeIt &a, const NodeIt &b) {
hegyi@819
   413
      gr = P.gr;
hegyi@819
   414
      edges.insert(edges.end(), P.edges.begin()+a.idx, P.edges.begin()+b.idx);
hegyi@819
   415
    }
hegyi@819
   416
hegyi@819
   417
    /// \brief Subpath constructor.
hegyi@819
   418
    ///
hegyi@819
   419
    /// Subpath defined by two edges. Contains edges in [a,b)
hegyi@819
   420
    /// \warning It is an error if the two edges are not in order!
hegyi@819
   421
    UndirPath(const UndirPath &P, const EdgeIt &a, const EdgeIt &b) {
hegyi@819
   422
      gr = P.gr;
hegyi@819
   423
      edges.insert(edges.end(), P.edges.begin()+a.idx, P.edges.begin()+b.idx);
hegyi@819
   424
    }
hegyi@819
   425
hegyi@819
   426
    /// Length of the path.
hegyi@819
   427
    size_t length() const { return edges.size(); }
hegyi@819
   428
    /// Returns whether the path is empty.
hegyi@819
   429
    bool empty() const { return edges.empty(); }
hegyi@819
   430
hegyi@819
   431
    /// Resets the path to an empty path.
hegyi@819
   432
    void clear() { edges.clear(); }
hegyi@819
   433
hegyi@819
   434
    /// \brief Starting point of the path.
hegyi@819
   435
    ///
hegyi@819
   436
    /// Starting point of the path.
hegyi@819
   437
    /// Returns INVALID if the path is empty.
alpar@986
   438
    GraphNode source() const {
alpar@986
   439
      return empty() ? INVALID : gr->source(edges[0]);
hegyi@819
   440
    }
hegyi@819
   441
    /// \brief End point of the path.
hegyi@819
   442
    ///
hegyi@819
   443
    /// End point of the path.
hegyi@819
   444
    /// Returns INVALID if the path is empty.
alpar@986
   445
    GraphNode target() const {
alpar@986
   446
      return empty() ? INVALID : gr->target(edges[length()-1]);
hegyi@819
   447
    }
hegyi@819
   448
hegyi@819
   449
    /// \brief Initializes node or edge iterator to point to the first
hegyi@819
   450
    /// node or edge.
hegyi@819
   451
    ///
hegyi@819
   452
    /// \sa nth
hegyi@819
   453
    template<typename It>
hegyi@819
   454
    It& first(It &i) const { return i=It(*this); }
hegyi@819
   455
hegyi@819
   456
    /// \brief Initializes node iterator to point to the node of a given index.
hegyi@819
   457
    NodeIt& nth(NodeIt &i, int n) const {
hegyi@819
   458
      return i=NodeIt(*this, n);
hegyi@819
   459
    }
hegyi@819
   460
hegyi@819
   461
    /// \brief Initializes edge iterator to point to the edge of a given index.
hegyi@819
   462
    EdgeIt& nth(EdgeIt &i, int n) const {
hegyi@819
   463
      return i=EdgeIt(*this, n);
hegyi@819
   464
    }
hegyi@819
   465
hegyi@819
   466
    /// Checks validity of a node or edge iterator.
hegyi@819
   467
    template<typename It>
hegyi@819
   468
    static
hegyi@819
   469
    bool valid(const It &i) { return i.valid(); }
hegyi@819
   470
hegyi@819
   471
    /// Steps the given node or edge iterator.
hegyi@819
   472
    template<typename It>
hegyi@819
   473
    static
hegyi@819
   474
    It& next(It &e) {
hegyi@819
   475
      return ++e;
hegyi@819
   476
    }
hegyi@819
   477
alpar@986
   478
    /// \brief Returns node iterator pointing to the target node of the
hegyi@819
   479
    /// given edge iterator.
alpar@986
   480
    NodeIt target(const EdgeIt& e) const {
hegyi@819
   481
      return NodeIt(*this, e.idx+1);
hegyi@819
   482
    }
hegyi@819
   483
alpar@986
   484
    /// \brief Returns node iterator pointing to the source node of the
hegyi@819
   485
    /// given edge iterator.
alpar@986
   486
    NodeIt source(const EdgeIt& e) const {
hegyi@819
   487
      return NodeIt(*this, e.idx);
hegyi@819
   488
    }
hegyi@819
   489
hegyi@819
   490
hegyi@819
   491
hegyi@819
   492
    /**
hegyi@819
   493
     * \brief Iterator class to iterate on the edges of the paths
hegyi@837
   494
     *
hegyi@819
   495
     * This class is used to iterate on the edges of the paths
hegyi@819
   496
     *
hegyi@819
   497
     * Of course it converts to Graph::Edge
hegyi@837
   498
     *
hegyi@819
   499
     * \todo Its interface differs from the standard edge iterator.
hegyi@819
   500
     * Yes, it shouldn't.
hegyi@819
   501
     */
hegyi@819
   502
    class EdgeIt {
hegyi@819
   503
      friend class UndirPath;
hegyi@819
   504
hegyi@819
   505
      int idx;
hegyi@819
   506
      const UndirPath *p;
hegyi@819
   507
    public:
hegyi@819
   508
      /// Default constructor
hegyi@819
   509
      EdgeIt() {}
hegyi@819
   510
      /// Invalid constructor
hegyi@819
   511
      EdgeIt(Invalid) : idx(-1), p(0) {}
hegyi@819
   512
      /// Constructor with starting point
hegyi@819
   513
      EdgeIt(const UndirPath &_p, int _idx = 0) :
hegyi@819
   514
	idx(_idx), p(&_p) { validate(); }
hegyi@819
   515
hegyi@819
   516
      ///Validity check
hegyi@819
   517
      bool valid() const { return idx!=-1; }
hegyi@819
   518
hegyi@819
   519
      ///Conversion to Graph::Edge
hegyi@819
   520
      operator GraphEdge () const {
hegyi@819
   521
	return valid() ? p->edges[idx] : INVALID;
hegyi@819
   522
      }
hegyi@819
   523
      /// Next edge
hegyi@819
   524
     EdgeIt& operator++() { ++idx; validate(); return *this; }
hegyi@819
   525
hegyi@819
   526
      /// Comparison operator
hegyi@819
   527
      bool operator==(const EdgeIt& e) const { return idx==e.idx; }
hegyi@819
   528
      /// Comparison operator
hegyi@819
   529
      bool operator!=(const EdgeIt& e) const { return idx!=e.idx; }
hegyi@819
   530
      /// Comparison operator
hegyi@819
   531
      bool operator<(const EdgeIt& e) const { return idx<e.idx; }
hegyi@819
   532
hegyi@819
   533
    private:
hegyi@819
   534
      // FIXME: comparison between signed and unsigned...
hegyi@819
   535
      // Jo ez igy? Vagy esetleg legyen a length() int?
hegyi@819
   536
      void validate() { if( size_t(idx) >= p->length() ) idx=-1; }
hegyi@819
   537
    };
hegyi@819
   538
hegyi@819
   539
    /**
hegyi@819
   540
     * \brief Iterator class to iterate on the nodes of the paths
hegyi@837
   541
     *
hegyi@819
   542
     * This class is used to iterate on the nodes of the paths
hegyi@819
   543
     *
hegyi@819
   544
     * Of course it converts to Graph::Node
hegyi@837
   545
     *
hegyi@819
   546
     * \todo Its interface differs from the standard node iterator.
hegyi@819
   547
     * Yes, it shouldn't.
hegyi@819
   548
     */
hegyi@819
   549
    class NodeIt {
hegyi@819
   550
      friend class UndirPath;
hegyi@819
   551
hegyi@819
   552
      int idx;
hegyi@819
   553
      const UndirPath *p;
hegyi@819
   554
    public:
hegyi@819
   555
      /// Default constructor
hegyi@819
   556
      NodeIt() {}
hegyi@819
   557
      /// Invalid constructor
hegyi@819
   558
      NodeIt(Invalid) : idx(-1), p(0) {}
hegyi@819
   559
      /// Constructor with starting point
hegyi@819
   560
      NodeIt(const UndirPath &_p, int _idx = 0) :
hegyi@819
   561
	idx(_idx), p(&_p) { validate(); }
hegyi@819
   562
hegyi@819
   563
      ///Validity check
hegyi@819
   564
      bool valid() const { return idx!=-1; }
hegyi@819
   565
hegyi@819
   566
      ///Conversion to Graph::Node
hegyi@819
   567
      operator const GraphNode& () const {
hegyi@819
   568
	if(idx >= p->length())
alpar@986
   569
	  return p->target();
hegyi@819
   570
	else if(idx >= 0)
alpar@986
   571
	  return p->gr->source(p->edges[idx]);
hegyi@819
   572
	else
hegyi@819
   573
	  return INVALID;
hegyi@819
   574
      }
hegyi@819
   575
      /// Next node
hegyi@819
   576
      NodeIt& operator++() { ++idx; validate(); return *this; }
hegyi@819
   577
hegyi@819
   578
      /// Comparison operator
hegyi@819
   579
      bool operator==(const NodeIt& e) const { return idx==e.idx; }
hegyi@819
   580
      /// Comparison operator
hegyi@819
   581
      bool operator!=(const NodeIt& e) const { return idx!=e.idx; }
hegyi@819
   582
       /// Comparison operator
hegyi@819
   583
     bool operator<(const NodeIt& e) const { return idx<e.idx; }
hegyi@819
   584
hegyi@819
   585
    private:
hegyi@819
   586
      void validate() { if( size_t(idx) > p->length() ) idx=-1; }
hegyi@819
   587
    };
hegyi@819
   588
hegyi@837
   589
    friend class Builder;
hegyi@819
   590
hegyi@819
   591
    /**
hegyi@819
   592
     * \brief Class to build paths
hegyi@837
   593
     *
hegyi@819
   594
     * This class is used to fill a path with edges.
hegyi@819
   595
     *
hegyi@819
   596
     * You can push new edges to the front and to the back of the path in
hegyi@819
   597
     * arbitrary order then you should commit these changes to the graph.
hegyi@819
   598
     *
hegyi@819
   599
     * Fundamentally, for most "Paths" (classes fulfilling the
hegyi@819
   600
     * PathConcept) while the builder is active (after the first modifying
hegyi@819
   601
     * operation and until the commit()) the original Path is in a
hegyi@819
   602
     * "transitional" state (operations ot it have undefined result). But
hegyi@819
   603
     * in the case of UndirPath the original path is unchanged until the
hegyi@819
   604
     * commit. However we don't recomend that you use this feature.
hegyi@819
   605
     */
hegyi@819
   606
    class Builder {
hegyi@819
   607
      UndirPath &P;
hegyi@819
   608
      Container front, back;
hegyi@819
   609
hegyi@819
   610
    public:
alpar@1228
   611
      ///\param _p the path you want to fill in.
hegyi@819
   612
      ///
alpar@1228
   613
      Builder(UndirPath &_p) : P(_p) {}
hegyi@819
   614
hegyi@819
   615
      /// Sets the starting node of the path.
hegyi@837
   616
hegyi@819
   617
      /// Sets the starting node of the path. Edge added to the path
hegyi@819
   618
      /// afterwards have to be incident to this node.
alpar@900
   619
      /// It should be called if and only if
alpar@900
   620
      /// the path is empty and before any call to
hegyi@819
   621
      /// \ref pushFront() or \ref pushBack()
hegyi@819
   622
      void setStartNode(const GraphNode &) {}
hegyi@819
   623
hegyi@819
   624
      ///Push a new edge to the front of the path
hegyi@819
   625
hegyi@819
   626
      ///Push a new edge to the front of the path.
hegyi@819
   627
      ///\sa setStartNode
hegyi@819
   628
      void pushFront(const GraphEdge& e) {
hegyi@819
   629
	front.push_back(e);
hegyi@819
   630
      }
hegyi@819
   631
hegyi@819
   632
      ///Push a new edge to the back of the path
hegyi@819
   633
hegyi@819
   634
      ///Push a new edge to the back of the path.
hegyi@819
   635
      ///\sa setStartNode
hegyi@819
   636
      void pushBack(const GraphEdge& e) {
hegyi@819
   637
	back.push_back(e);
hegyi@819
   638
      }
hegyi@819
   639
hegyi@819
   640
      ///Commit the changes to the path.
hegyi@819
   641
      void commit() {
hegyi@819
   642
	if( !(front.empty() && back.empty()) ) {
hegyi@819
   643
	  Container tmp;
hegyi@819
   644
	  tmp.reserve(front.size()+back.size()+P.length());
hegyi@819
   645
	  tmp.insert(tmp.end(), front.rbegin(), front.rend());
hegyi@819
   646
	  tmp.insert(tmp.end(), P.edges.begin(), P.edges.end());
hegyi@819
   647
	  tmp.insert(tmp.end(), back.begin(), back.end());
hegyi@819
   648
	  P.edges.swap(tmp);
hegyi@819
   649
	  front.clear();
hegyi@819
   650
	  back.clear();
hegyi@819
   651
	}
hegyi@819
   652
      }
hegyi@819
   653
hegyi@819
   654
hegyi@819
   655
      ///Reserve storage for the builder in advance.
hegyi@819
   656
hegyi@837
   657
      ///If you know a reasonable upper bound of the number of the edges
hegyi@837
   658
      ///to add to the front, using this function you can speed up the building.
hegyi@819
   659
hegyi@837
   660
      void reserveFront(size_t r) {front.reserve(r);}
hegyi@837
   661
hegyi@837
   662
      ///Reserve storage for the builder in advance.
hegyi@837
   663
hegyi@837
   664
      ///If you know a reasonable upper bound of the number of the edges
hegyi@837
   665
      ///to add to the back, using this function you can speed up the building.
hegyi@837
   666
hegyi@837
   667
      void reserveBack(size_t r) {back.reserve(r);}
hegyi@831
   668
hegyi@819
   669
    private:
hegyi@819
   670
      bool empty() {
hegyi@819
   671
	return front.empty() && back.empty() && P.empty();
hegyi@819
   672
      }
hegyi@819
   673
alpar@986
   674
      GraphNode source() const {
hegyi@819
   675
	if( ! front.empty() )
alpar@986
   676
	  return P.gr->source(front[front.size()-1]);
hegyi@819
   677
	else if( ! P.empty() )
alpar@986
   678
	  return P.gr->source(P.edges[0]);
hegyi@819
   679
	else if( ! back.empty() )
alpar@986
   680
	  return P.gr->source(back[0]);
hegyi@819
   681
	else
hegyi@819
   682
	  return INVALID;
hegyi@819
   683
      }
alpar@986
   684
      GraphNode target() const {
hegyi@819
   685
	if( ! back.empty() )
alpar@986
   686
	  return P.gr->target(back[back.size()-1]);
hegyi@819
   687
	else if( ! P.empty() )
alpar@986
   688
	  return P.gr->target(P.edges[P.length()-1]);
hegyi@819
   689
	else if( ! front.empty() )
alpar@986
   690
	  return P.gr->target(front[0]);
hegyi@819
   691
	else
hegyi@819
   692
	  return INVALID;
hegyi@819
   693
      }
hegyi@819
   694
hegyi@819
   695
    };
hegyi@819
   696
hegyi@819
   697
  };
hegyi@819
   698
hegyi@819
   699
hegyi@819
   700
  ///@}
hegyi@819
   701
alpar@921
   702
} // namespace lemon
hegyi@819
   703
alpar@921
   704
#endif // LEMON_PATH_H