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