src/work/johanna/unionfind.h
author marci
Thu, 29 Apr 2004 16:04:27 +0000
changeset 473 2cef25dcde3f
parent 394 3a34c5626e52
child 481 54d8feda437b
permissions -rw-r--r--
ledagraph
beckerjc@150
     1
// -*- c++ -*- //
beckerjc@218
     2
#ifndef HUGO_UNION_FIND_H
beckerjc@218
     3
#define HUGO_UNION_FIND_H
beckerjc@150
     4
beckerjc@462
     5
//!ingroup auxdat
beckerjc@462
     6
//!\file
beckerjc@462
     7
//!\brief Union-Find data structures.
beckerjc@462
     8
beckerjc@462
     9
beckerjc@150
    10
#include <vector>
beckerjc@394
    11
#include <list>
beckerjc@150
    12
#include <utility>
beckerjc@394
    13
#include <algorithm>
beckerjc@394
    14
beckerjc@394
    15
#include <invalid.h>
beckerjc@150
    16
beckerjc@150
    17
namespace hugo {
beckerjc@150
    18
beckerjc@462
    19
  //! \addtogroup auxdat
beckerjc@462
    20
  //! @{
beckerjc@462
    21
beckerjc@462
    22
  /**
beckerjc@462
    23
   * \brief A \e Union-Find data structure implementation
beckerjc@462
    24
   *
beckerjc@462
    25
   * The class implements the \e Union-Find data structure. 
beckerjc@462
    26
   * The union operation uses rank heuristic, while
beckerjc@462
    27
   * the find operation uses path compresson.
beckerjc@462
    28
   * This is a very simple but efficient implementation, providing 
beckerjc@462
    29
   * only four methods: join (union), find, insert and size.
beckerjc@462
    30
   * For more features see the \ref UnionFindEnum class.
beckerjc@462
    31
   *
beckerjc@462
    32
   * \pre The elements are automatically added only if the map 
beckerjc@462
    33
   * given to the constructor was filled with -1's. Otherwise you
beckerjc@462
    34
   * need to add all the elements by the \ref insert() method.
beckerjc@462
    35
   */
beckerjc@462
    36
beckerjc@150
    37
  template <typename T, typename TIntMap>
beckerjc@150
    38
  class UnionFind {
beckerjc@150
    39
    
beckerjc@150
    40
  public:
beckerjc@150
    41
    typedef T ElementType;
beckerjc@150
    42
    typedef std::pair<int,int> PairType;
beckerjc@150
    43
beckerjc@150
    44
  private:
beckerjc@150
    45
    std::vector<PairType> data;
beckerjc@150
    46
    TIntMap& map;
beckerjc@150
    47
beckerjc@150
    48
  public:
beckerjc@150
    49
    UnionFind(TIntMap& m) : map(m) {}
beckerjc@150
    50
beckerjc@462
    51
    /**
beckerjc@462
    52
     * \brief Returns the index of the element's component.
beckerjc@462
    53
     *
beckerjc@462
    54
     * The method returns the index of the element's component.
beckerjc@462
    55
     * This is an integer between zero and the number of inserted elements.
beckerjc@462
    56
     */
beckerjc@150
    57
beckerjc@394
    58
    int find(T a)
beckerjc@150
    59
    {
beckerjc@349
    60
      int comp0 = map[a];
beckerjc@150
    61
      if (comp0 < 0) {
beckerjc@394
    62
	return insert(a);
beckerjc@150
    63
      }
beckerjc@150
    64
      int comp = comp0;
beckerjc@150
    65
      int next;
beckerjc@150
    66
      while ( (next = data[comp].first) != comp) {
beckerjc@150
    67
	comp = next;
beckerjc@150
    68
      }
beckerjc@150
    69
      while ( (next = data[comp0].first) != comp) {
beckerjc@150
    70
	data[comp0].first = comp;
beckerjc@150
    71
	comp0 = next;
beckerjc@150
    72
      }
beckerjc@150
    73
beckerjc@150
    74
      return comp;
beckerjc@150
    75
    }
beckerjc@150
    76
beckerjc@462
    77
    /**
beckerjc@462
    78
     * \brief Insert a new element into the structure.
beckerjc@462
    79
     *
beckerjc@462
    80
     * This method inserts a new element into the data structure. 
beckerjc@462
    81
     *
beckerjc@462
    82
     * It is not required to use this method:
beckerjc@462
    83
     * if the map given to the constructor was filled 
beckerjc@462
    84
     * with -1's then it is called automatically
beckerjc@462
    85
     * on the first \ref find or \ref join.
beckerjc@462
    86
     *
beckerjc@462
    87
     * The method returns the index of the new component.
beckerjc@462
    88
     */
beckerjc@462
    89
beckerjc@394
    90
    int insert(T a)
beckerjc@150
    91
    {
beckerjc@150
    92
      int n = data.size();
beckerjc@394
    93
      data.push_back(std::make_pair(n, 1));
beckerjc@150
    94
      map.set(a,n);
beckerjc@150
    95
      return n;
beckerjc@150
    96
    }
beckerjc@150
    97
beckerjc@462
    98
    /**
beckerjc@462
    99
     * \brief Joining the components of element \e a and element \e b.
beckerjc@462
   100
     *
beckerjc@462
   101
     * This is the \e union operation of the Union-Find structure. 
beckerjc@462
   102
     * Joins the component of elemenent \e a and component of
beckerjc@462
   103
     * element \e b. If \e a and \e b are in the same component then
beckerjc@462
   104
     * it returns false otherwise it returns true.
beckerjc@462
   105
     */
beckerjc@462
   106
beckerjc@394
   107
    bool join(T a, T b)
beckerjc@150
   108
    {
beckerjc@394
   109
      int ca = find(a);
beckerjc@394
   110
      int cb = find(b);
beckerjc@150
   111
beckerjc@150
   112
      if ( ca == cb ) 
beckerjc@150
   113
	return false;
beckerjc@150
   114
beckerjc@150
   115
      if ( data[ca].second > data[cb].second ) {
beckerjc@150
   116
	data[cb].first = ca;
beckerjc@150
   117
	data[ca].second += data[cb].second;
beckerjc@150
   118
      }
beckerjc@150
   119
      else {
beckerjc@150
   120
	data[ca].first = cb;
beckerjc@150
   121
	data[cb].second += data[ca].second;
beckerjc@150
   122
      }
beckerjc@150
   123
      return true;
beckerjc@150
   124
    }
beckerjc@150
   125
beckerjc@462
   126
    /**
beckerjc@462
   127
     * \brief Returns the size of the component of element \e a.
beckerjc@462
   128
     *
beckerjc@462
   129
     * Returns the size of the component of element \e a.
beckerjc@462
   130
     */
beckerjc@462
   131
beckerjc@394
   132
    int size(T a)
beckerjc@218
   133
    {
beckerjc@394
   134
      int ca = find(a);
beckerjc@218
   135
      return data[ca].second;
beckerjc@218
   136
    }
beckerjc@218
   137
beckerjc@150
   138
  };
beckerjc@150
   139
beckerjc@394
   140
beckerjc@394
   141
beckerjc@394
   142
beckerjc@394
   143
  /*******************************************************/
beckerjc@394
   144
beckerjc@394
   145
beckerjc@462
   146
#ifdef DEVELOPMENT_DOCS
beckerjc@462
   147
beckerjc@462
   148
  /**
beckerjc@462
   149
   * \brief The auxiliary class for the \ref UnionFindEnum class.
beckerjc@462
   150
   *
beckerjc@462
   151
   * In the \ref UnionFindEnum class all components are represented as
beckerjc@462
   152
   * a std::list. 
beckerjc@462
   153
   * Items of these lists are UnionFindEnumItem structures.
beckerjc@462
   154
   *
beckerjc@462
   155
   * The class has four fields:
beckerjc@462
   156
   *  - T me - the actual element 
beckerjc@462
   157
   *  - IIter parent - the parent of the element in the union-find structure
beckerjc@462
   158
   *  - int size - the size of the component of the element. 
beckerjc@462
   159
   *            Only valid if the element
beckerjc@462
   160
   *            is the leader of the component.
beckerjc@462
   161
   *  - CIter my_class - pointer into the list of components 
beckerjc@462
   162
   *            pointing to the component of the element.
beckerjc@462
   163
   *            Only valid if the element is the leader of the component.
beckerjc@462
   164
   */
beckerjc@462
   165
beckerjc@462
   166
#endif
beckerjc@394
   167
beckerjc@394
   168
  template <typename T>
beckerjc@394
   169
  struct UnionFindEnumItem {
beckerjc@394
   170
beckerjc@394
   171
    typedef std::list<UnionFindEnumItem> ItemList;
beckerjc@394
   172
    typedef std::list<ItemList> ClassList;
beckerjc@394
   173
    typedef typename ItemList::iterator IIter;
beckerjc@394
   174
    typedef typename ClassList::iterator CIter;
beckerjc@394
   175
beckerjc@394
   176
    T me;
beckerjc@394
   177
    IIter parent;
beckerjc@394
   178
    int size;
beckerjc@394
   179
    CIter my_class;
beckerjc@394
   180
beckerjc@394
   181
    UnionFindEnumItem() {}
beckerjc@394
   182
    UnionFindEnumItem(const T &_me, CIter _my_class): 
beckerjc@394
   183
      me(_me), size(1), my_class(_my_class) {}
beckerjc@394
   184
  };
beckerjc@394
   185
beckerjc@462
   186
beckerjc@462
   187
  /**
beckerjc@462
   188
   * \brief A \e Union-Find data structure implementation which
beckerjc@462
   189
   * is able to enumerate the components.
beckerjc@462
   190
   *
beckerjc@462
   191
   * The class implements an \e Union-Find data structure
beckerjc@462
   192
   * which is able to enumerate the components and the items in
beckerjc@462
   193
   * a component. If you don't need this feature then perhaps it's
beckerjc@462
   194
   * better to use the \ref UnionFind class which is more efficient.
beckerjc@462
   195
   *
beckerjc@462
   196
   * The union operation uses rank heuristic, while
beckerjc@462
   197
   * the find operation uses path compresson.
beckerjc@462
   198
   *
beckerjc@462
   199
   * \pre You
beckerjc@462
   200
   * need to add all the elements by the \ref insert() method.
beckerjc@462
   201
   */
beckerjc@462
   202
beckerjc@462
   203
beckerjc@394
   204
  template <typename T, template <typename Item> class Map>
beckerjc@394
   205
  class UnionFindEnum {
beckerjc@394
   206
beckerjc@394
   207
    typedef std::list<UnionFindEnumItem<T> > ItemList;
beckerjc@394
   208
    typedef std::list<ItemList> ClassList;
beckerjc@394
   209
    typedef typename ItemList::iterator IIter;
beckerjc@394
   210
    typedef typename ItemList::const_iterator IcIter;
beckerjc@394
   211
    typedef typename ClassList::iterator CIter;
beckerjc@394
   212
    typedef typename ClassList::const_iterator CcIter;
beckerjc@394
   213
beckerjc@394
   214
  public:
beckerjc@394
   215
    typedef T ElementType;
beckerjc@394
   216
    typedef UnionFindEnumItem<T> ItemType;
beckerjc@394
   217
    typedef Map< IIter > MapType;
beckerjc@394
   218
beckerjc@394
   219
  private:
beckerjc@394
   220
    MapType& m;
beckerjc@394
   221
    ClassList classes;
beckerjc@394
   222
beckerjc@394
   223
    IIter _find(IIter a) const {
beckerjc@394
   224
      IIter comp = a;
beckerjc@394
   225
      IIter next;
beckerjc@394
   226
      while( (next = comp->parent) != comp ) {
beckerjc@394
   227
	comp = next;
beckerjc@394
   228
      }
beckerjc@394
   229
beckerjc@394
   230
      IIter comp1 = a;
beckerjc@394
   231
      while( (next = comp1->parent) != comp ) {
beckerjc@394
   232
	comp1->parent = comp->parent;
beckerjc@394
   233
	comp1 = next;
beckerjc@394
   234
      }
beckerjc@394
   235
      return comp;
beckerjc@394
   236
    }
beckerjc@394
   237
beckerjc@394
   238
  public:
beckerjc@394
   239
    UnionFindEnum(MapType& _m) : m(_m) {}
beckerjc@394
   240
beckerjc@462
   241
beckerjc@462
   242
    /**
beckerjc@462
   243
     * \brief Insert the given element into a new component.
beckerjc@462
   244
     *
beckerjc@462
   245
     * This method creates a new component consisting only of the
beckerjc@462
   246
     * given element.
beckerjc@462
   247
     */
beckerjc@462
   248
beckerjc@394
   249
    void insert(const T &a)
beckerjc@394
   250
    {
beckerjc@394
   251
beckerjc@394
   252
beckerjc@394
   253
      classes.push_back(ItemList());
beckerjc@394
   254
      CIter aclass = classes.end();
beckerjc@394
   255
      --aclass;
beckerjc@394
   256
beckerjc@394
   257
      ItemList &alist = *aclass;
beckerjc@394
   258
      alist.push_back(ItemType(a, aclass));
beckerjc@394
   259
      IIter ai = alist.begin();
beckerjc@394
   260
beckerjc@394
   261
      ai->parent = ai;
beckerjc@394
   262
      m.set(a, ai);
beckerjc@394
   263
beckerjc@394
   264
    }
beckerjc@394
   265
beckerjc@462
   266
    /**
beckerjc@462
   267
     * \brief Find the leader of the component of the given element.
beckerjc@462
   268
     *
beckerjc@462
   269
     * The method returns the leader of the component of the given element.
beckerjc@462
   270
     */
beckerjc@462
   271
beckerjc@394
   272
    T find(const T &a) const {
beckerjc@394
   273
      return _find(m[a])->me;
beckerjc@394
   274
    }
beckerjc@394
   275
beckerjc@462
   276
beckerjc@462
   277
    /**
beckerjc@462
   278
     * \brief Joining the component of element \e a and element \e b.
beckerjc@462
   279
     *
beckerjc@462
   280
     * This is the \e union operation of the Union-Find structure. 
beckerjc@462
   281
     * Joins the component of elemenent \e a and component of
beckerjc@462
   282
     * element \e b. If \e a and \e b are in the same component then
beckerjc@462
   283
     * returns false else returns true.
beckerjc@462
   284
     */
beckerjc@462
   285
beckerjc@394
   286
    bool join(T a, T b) {
beckerjc@394
   287
beckerjc@394
   288
      IIter ca = _find(m[a]);
beckerjc@394
   289
      IIter cb = _find(m[b]);
beckerjc@394
   290
beckerjc@394
   291
      if ( ca == cb ) {
beckerjc@394
   292
	return false;
beckerjc@394
   293
      }
beckerjc@394
   294
beckerjc@394
   295
      if ( ca->size > cb->size ) {
beckerjc@394
   296
beckerjc@394
   297
	cb->parent = ca->parent;
beckerjc@394
   298
	ca->size += cb->size;
beckerjc@394
   299
	
beckerjc@394
   300
	ItemList &alist = *ca->my_class;
beckerjc@394
   301
	alist.splice(alist.end(),*cb->my_class);
beckerjc@394
   302
beckerjc@394
   303
	classes.erase(cb->my_class);
beckerjc@394
   304
	cb->my_class = 0;
beckerjc@394
   305
      }
beckerjc@394
   306
      else {
beckerjc@394
   307
beckerjc@394
   308
	ca->parent = cb->parent;
beckerjc@394
   309
	cb->size += ca->size;
beckerjc@394
   310
	
beckerjc@394
   311
	ItemList &blist = *cb->my_class;
beckerjc@394
   312
	blist.splice(blist.end(),*ca->my_class);
beckerjc@394
   313
beckerjc@394
   314
	classes.erase(ca->my_class);
beckerjc@394
   315
	ca->my_class = 0;
beckerjc@394
   316
      }
beckerjc@394
   317
beckerjc@394
   318
      return true;
beckerjc@394
   319
    }
beckerjc@394
   320
beckerjc@462
   321
beckerjc@462
   322
    /**
beckerjc@462
   323
     * \brief Returns the size of the component of element \e a.
beckerjc@462
   324
     *
beckerjc@462
   325
     * Returns the size of the component of element \e a.
beckerjc@462
   326
     */
beckerjc@462
   327
beckerjc@394
   328
    int size(const T &a) const {
beckerjc@394
   329
      return _find(m[a])->size;
beckerjc@394
   330
    }
beckerjc@394
   331
beckerjc@462
   332
beckerjc@462
   333
    /**
beckerjc@462
   334
     * \brief Split up the component of the element. 
beckerjc@462
   335
     *
beckerjc@462
   336
     * Splitting the component of the element into sigleton
beckerjc@462
   337
     * components (component of size one).
beckerjc@462
   338
     */
beckerjc@462
   339
beckerjc@394
   340
    void split(const T &a) {
beckerjc@394
   341
beckerjc@394
   342
      IIter ca = _find(m[a]);
beckerjc@394
   343
 
beckerjc@394
   344
      if ( ca->size == 1 )
beckerjc@394
   345
	return;
beckerjc@394
   346
      
beckerjc@394
   347
      CIter aclass = ca->my_class;
beckerjc@394
   348
beckerjc@394
   349
      for(IIter curr = ca; ++curr != aclass->end(); curr=ca) {
beckerjc@394
   350
	classes.push_back(ItemList());
beckerjc@394
   351
	CIter nl = --classes.end();
beckerjc@394
   352
	nl->splice(nl->end(), *aclass, curr);
beckerjc@394
   353
beckerjc@394
   354
	curr->size=1;
beckerjc@394
   355
	curr->parent=curr;
beckerjc@394
   356
	curr->my_class = nl;
beckerjc@394
   357
      }
beckerjc@394
   358
beckerjc@394
   359
      ca->size=1;
beckerjc@394
   360
      return;
beckerjc@394
   361
    }
beckerjc@394
   362
beckerjc@462
   363
beckerjc@462
   364
    /**
beckerjc@462
   365
     * \brief Set the given element to the leader element of its component.
beckerjc@462
   366
     *
beckerjc@462
   367
     * Set the given element to the leader element of its component.
beckerjc@462
   368
     */
beckerjc@462
   369
beckerjc@462
   370
    void makeRep(const T &a) {
beckerjc@462
   371
beckerjc@462
   372
      IIter ia = m[a];
beckerjc@462
   373
      IIter la = _find(ia);
beckerjc@462
   374
      if (la == ia) return;
beckerjc@462
   375
beckerjc@462
   376
      ia->my_class = la->my_class;
beckerjc@462
   377
      la->my_class = 0;
beckerjc@462
   378
beckerjc@462
   379
      ia->size = la->size;
beckerjc@462
   380
beckerjc@462
   381
      CIter l = ia->my_class;
beckerjc@462
   382
      l->splice(l->begin(),*l,ia);
beckerjc@462
   383
beckerjc@462
   384
      ia->parent = ia;
beckerjc@462
   385
      la->parent = ia;
beckerjc@462
   386
    }
beckerjc@462
   387
beckerjc@462
   388
beckerjc@462
   389
    /**
beckerjc@462
   390
     * \brief Remove the given element from the structure.
beckerjc@462
   391
     *
beckerjc@462
   392
     * Remove the given element from the structure.
beckerjc@462
   393
     *
beckerjc@462
   394
     * Removes the element from its component and if the component becomes
beckerjc@462
   395
     * empty then removes that component from the component list.
beckerjc@462
   396
     */
beckerjc@394
   397
    void erase(const T &a) {
beckerjc@394
   398
beckerjc@394
   399
      IIter ma = m[a];
beckerjc@394
   400
      if (ma == 0) return;
beckerjc@394
   401
beckerjc@394
   402
      IIter la = _find(ma);
beckerjc@394
   403
      if (la == ma) {
beckerjc@394
   404
	if (ma -> size == 1){
beckerjc@394
   405
	  classes.erase(ma->my_class);
beckerjc@394
   406
	  m.set(a,0);
beckerjc@394
   407
	  return;
beckerjc@394
   408
	}
beckerjc@394
   409
	++la;
beckerjc@462
   410
	la->size = ma->size; 
beckerjc@394
   411
	la->my_class = ma->my_class;	
beckerjc@394
   412
      }
beckerjc@394
   413
beckerjc@394
   414
      for (IIter i = la; i != la->my_class->end(); ++i) {
beckerjc@394
   415
	i->parent = la;
beckerjc@394
   416
      }
beckerjc@394
   417
beckerjc@462
   418
      la->size--;
beckerjc@394
   419
      la->my_class->erase(ma);
beckerjc@394
   420
      m.set(a,0);
beckerjc@394
   421
    }
beckerjc@394
   422
beckerjc@462
   423
    /**
beckerjc@462
   424
     * \brief Removes the component of the given element from the structure.
beckerjc@462
   425
     *
beckerjc@462
   426
     * Removes the component of the given element from the structure.
beckerjc@462
   427
     */
beckerjc@462
   428
beckerjc@394
   429
    void eraseClass(const T &a) {
beckerjc@394
   430
      IIter ma = m[a];
beckerjc@394
   431
      if (ma == 0) return;
beckerjc@394
   432
#     ifdef DEBUG
beckerjc@394
   433
      CIter c = _find(ma)->my_class;
beckerjc@394
   434
      for (IIter i=c->begin(); i!=c->end(); ++i)
beckerjc@394
   435
	m.set(i->me, 0);
beckerjc@394
   436
#     endif
beckerjc@394
   437
      classes.erase(_find(ma)->my_class);
beckerjc@394
   438
    }
beckerjc@394
   439
beckerjc@394
   440
beckerjc@394
   441
    class ClassIt {
beckerjc@394
   442
      friend class UnionFindEnum;
beckerjc@394
   443
beckerjc@394
   444
      CcIter i;
beckerjc@394
   445
    public:
beckerjc@394
   446
      ClassIt(Invalid): i(0) {}
beckerjc@394
   447
      ClassIt() {}
beckerjc@394
   448
      
beckerjc@394
   449
      operator const T& () const { 
beckerjc@394
   450
	ItemList const &ll = *i;
beckerjc@394
   451
	return (ll.begin())->me; }
beckerjc@394
   452
      bool operator == (ClassIt it) const {
beckerjc@394
   453
	return (i == it.i);
beckerjc@394
   454
      }
beckerjc@394
   455
      bool operator != (ClassIt it) const {
beckerjc@394
   456
	return (i != it.i);
beckerjc@394
   457
      }
beckerjc@394
   458
      bool operator < (ClassIt it) const {
beckerjc@394
   459
	return (i < it.i);
beckerjc@394
   460
      }
beckerjc@394
   461
beckerjc@394
   462
      bool valid() const { return i != 0; }
beckerjc@394
   463
    private:
beckerjc@394
   464
      void first(const ClassList &l) { i = l.begin(); validate(l); }
beckerjc@394
   465
      void next(const ClassList &l) {
beckerjc@394
   466
	++i; 
beckerjc@394
   467
	validate(l);
beckerjc@394
   468
      }
beckerjc@394
   469
      void validate(const ClassList &l) {
beckerjc@394
   470
	if ( i == l.end() ) 
beckerjc@394
   471
	  i = 0;
beckerjc@394
   472
      }
beckerjc@394
   473
    };
beckerjc@394
   474
beckerjc@462
   475
    /**
beckerjc@462
   476
     * \brief Sets the iterator to point to the first component.
beckerjc@462
   477
     * 
beckerjc@462
   478
     * Sets the iterator to point to the first component.
beckerjc@462
   479
     *
beckerjc@462
   480
     * With the \ref first, \ref valid and \ref next methods you can
beckerjc@462
   481
     * iterate through the components. For example:
beckerjc@462
   482
     * \code
beckerjc@462
   483
     * UnionFindEnum<Graph::Node, Graph::NodeMap>::MapType map(G);
beckerjc@462
   484
     * UnionFindEnum<Graph::Node, Graph::NodeMap> U(map);
beckerjc@462
   485
     * UnionFindEnum<Graph::Node, Graph::NodeMap>::ClassIt iter;
beckerjc@462
   486
     *  for (U.first(iter); U.valid(iter); U.next(iter)) {
beckerjc@462
   487
     *    // iter is convertible to Graph::Node
beckerjc@462
   488
     *    cout << iter << endl;
beckerjc@462
   489
     *  }
beckerjc@462
   490
     * \endcode
beckerjc@462
   491
     */
beckerjc@394
   492
beckerjc@394
   493
    ClassIt& first(ClassIt& it) const {
beckerjc@394
   494
      it.first(classes);
beckerjc@394
   495
      return it;
beckerjc@394
   496
    }
beckerjc@394
   497
beckerjc@462
   498
    /**
beckerjc@462
   499
     * \brief Returns whether the iterator is valid.
beckerjc@462
   500
     *
beckerjc@462
   501
     * Returns whether the iterator is valid.
beckerjc@462
   502
     *
beckerjc@462
   503
     * With the \ref first, \ref valid and \ref next methods you can
beckerjc@462
   504
     * iterate through the components. See the example here: \ref first.
beckerjc@462
   505
     */
beckerjc@462
   506
beckerjc@394
   507
    bool valid(ClassIt const &it) const {
beckerjc@394
   508
      return it.valid(); 
beckerjc@394
   509
    }
beckerjc@394
   510
beckerjc@462
   511
    /**
beckerjc@462
   512
     * \brief Steps the iterator to the next component. 
beckerjc@462
   513
     *
beckerjc@462
   514
     * Steps the iterator to the next component.
beckerjc@462
   515
     *
beckerjc@462
   516
     * With the \ref first, \ref valid and \ref next methods you can
beckerjc@462
   517
     * iterate through the components. See the example here: \ref first.
beckerjc@462
   518
     */
beckerjc@462
   519
beckerjc@394
   520
    ClassIt& next(ClassIt& it) const {
beckerjc@394
   521
      it.next(classes);
beckerjc@394
   522
      return it;
beckerjc@394
   523
    }
beckerjc@394
   524
beckerjc@394
   525
beckerjc@394
   526
    class ItemIt {
beckerjc@394
   527
      friend class UnionFindEnum;
beckerjc@394
   528
beckerjc@394
   529
      IcIter i;
beckerjc@394
   530
      const ItemList *l;
beckerjc@394
   531
    public:
beckerjc@394
   532
      ItemIt(Invalid): i(0) {}
beckerjc@394
   533
      ItemIt() {}
beckerjc@394
   534
      
beckerjc@394
   535
      operator const T& () const { return i->me; }
beckerjc@394
   536
      bool operator == (ItemIt it) const {
beckerjc@394
   537
	return (i == it.i);
beckerjc@394
   538
      }
beckerjc@394
   539
      bool operator != (ItemIt it) const {
beckerjc@394
   540
	return (i != it.i);
beckerjc@394
   541
      }
beckerjc@394
   542
      bool operator < (ItemIt it) const {
beckerjc@394
   543
	return (i < it.i);
beckerjc@394
   544
      }
beckerjc@394
   545
beckerjc@394
   546
      bool valid() const { return i != 0; }
beckerjc@394
   547
    private:
beckerjc@394
   548
      void first(const ItemList &il) { l=&il; i = l->begin(); validate(); }
beckerjc@394
   549
      void next() {
beckerjc@394
   550
	++i; 
beckerjc@394
   551
	validate();
beckerjc@394
   552
      }
beckerjc@394
   553
      void validate() {
beckerjc@394
   554
	if ( i == l->end() ) 
beckerjc@394
   555
	  i = 0;
beckerjc@394
   556
      }
beckerjc@394
   557
    };
beckerjc@394
   558
beckerjc@394
   559
beckerjc@462
   560
beckerjc@462
   561
    /**
beckerjc@462
   562
     * \brief Sets the iterator to point to the first element of the component.
beckerjc@462
   563
     * 
beckerjc@462
   564
     * \anchor first2 
beckerjc@462
   565
     * Sets the iterator to point to the first element of the component.
beckerjc@462
   566
     *
beckerjc@462
   567
     * With the \ref first2 "first", \ref valid2 "valid" 
beckerjc@462
   568
     * and \ref next2 "next" methods you can
beckerjc@462
   569
     * iterate through the elements of a component. For example
beckerjc@462
   570
     * (iterating through the component of the node \e node):
beckerjc@462
   571
     * \code
beckerjc@462
   572
     * Graph::Node node = ...;
beckerjc@462
   573
     * UnionFindEnum<Graph::Node, Graph::NodeMap>::MapType map(G);
beckerjc@462
   574
     * UnionFindEnum<Graph::Node, Graph::NodeMap> U(map);
beckerjc@462
   575
     * UnionFindEnum<Graph::Node, Graph::NodeMap>::ItemIt iiter;
beckerjc@462
   576
     *   for (U.first(iiter, node); U.valid(iiter); U.next(iiter)) {
beckerjc@462
   577
     *     // iiter is convertible to Graph::Node
beckerjc@462
   578
     *     cout << iiter << endl;
beckerjc@462
   579
     *   }
beckerjc@462
   580
     * \endcode
beckerjc@462
   581
     */
beckerjc@462
   582
    
beckerjc@394
   583
    ItemIt& first(ItemIt& it, const T& a) const {
beckerjc@394
   584
      it.first( * _find(m[a])->my_class );
beckerjc@394
   585
      return it;
beckerjc@394
   586
    }
beckerjc@394
   587
beckerjc@462
   588
    /**
beckerjc@462
   589
     * \brief Returns whether the iterator is valid.
beckerjc@462
   590
     *
beckerjc@462
   591
     * \anchor valid2
beckerjc@462
   592
     * Returns whether the iterator is valid.
beckerjc@462
   593
     *
beckerjc@462
   594
     * With the \ref first2 "first", \ref valid2 "valid" 
beckerjc@462
   595
     * and \ref next2 "next" methods you can
beckerjc@462
   596
     * iterate through the elements of a component.
beckerjc@462
   597
     * See the example here: \ref first2 "first".
beckerjc@462
   598
     */
beckerjc@462
   599
beckerjc@394
   600
    bool valid(ItemIt const &it) const {
beckerjc@394
   601
      return it.valid(); 
beckerjc@394
   602
    }
beckerjc@394
   603
beckerjc@462
   604
    /**
beckerjc@462
   605
     * \brief Steps the iterator to the next component. 
beckerjc@462
   606
     *
beckerjc@462
   607
     * \anchor next2
beckerjc@462
   608
     * Steps the iterator to the next component.
beckerjc@462
   609
     *
beckerjc@462
   610
     * With the \ref first2 "first", \ref valid2 "valid" 
beckerjc@462
   611
     * and \ref next2 "next" methods you can
beckerjc@462
   612
     * iterate through the elements of a component.
beckerjc@462
   613
     * See the example here: \ref first2 "first".
beckerjc@462
   614
     */
beckerjc@462
   615
beckerjc@394
   616
    ItemIt& next(ItemIt& it) const {
beckerjc@394
   617
      it.next();
beckerjc@394
   618
      return it;
beckerjc@394
   619
    }
beckerjc@394
   620
    
beckerjc@462
   621
  };
beckerjc@394
   622
beckerjc@394
   623
beckerjc@462
   624
  //! @}
beckerjc@394
   625
beckerjc@150
   626
} //namespace hugo
beckerjc@150
   627
beckerjc@218
   628
#endif //HUGO_UNION_FIND_H