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