lemon/unionfind.h
author deba
Fri, 15 Jun 2007 14:36:24 +0000
changeset 2457 8c791ee69a45
parent 2391 14a343be7a5a
child 2505 1bb471764ab8
permissions -rw-r--r--
Improvments in min cost flow algorithms
- improved cycle cancelling
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@2391
     5
 * Copyright (C) 2003-2007
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
deba@2308
    36
  /// \ingroup auxdat
deba@2308
    37
  ///
deba@2205
    38
  /// \brief A \e Union-Find data structure implementation
deba@2205
    39
  ///
deba@2205
    40
  /// The class implements the \e Union-Find data structure. 
deba@2205
    41
  /// The union operation uses rank heuristic, while
deba@2205
    42
  /// the find operation uses path compression.
deba@2205
    43
  /// This is a very simple but efficient implementation, providing 
deba@2205
    44
  /// only four methods: join (union), find, insert and size.
deba@2205
    45
  /// For more features see the \ref UnionFindEnum class.
deba@2205
    46
  ///
deba@2205
    47
  /// It is primarily used in Kruskal algorithm for finding minimal
deba@2205
    48
  /// cost spanning tree in a graph.
deba@2205
    49
  /// \sa kruskal()
deba@2205
    50
  ///
deba@2205
    51
  /// \pre You need to add all the elements by the \ref insert()
deba@2205
    52
  /// method.  
deba@2308
    53
  template <typename _ItemIntMap>
beckerjc@483
    54
  class UnionFind {
beckerjc@483
    55
  public:
deba@2308
    56
deba@2308
    57
    typedef _ItemIntMap ItemIntMap;
deba@2308
    58
    typedef typename ItemIntMap::Key Item;
beckerjc@483
    59
beckerjc@483
    60
  private:
deba@2205
    61
    // If the items vector stores negative value for an item then
deba@2205
    62
    // that item is root item and it has -items[it] component size.
deba@2205
    63
    // Else the items[it] contains the index of the parent.
deba@2205
    64
    std::vector<int> items;
deba@2205
    65
    ItemIntMap& index;
deba@2205
    66
deba@2205
    67
    bool rep(int idx) const {
deba@2205
    68
      return items[idx] < 0;
deba@2205
    69
    }
deba@2205
    70
deba@2205
    71
    int repIndex(int idx) const {
deba@2205
    72
      int k = idx;
deba@2205
    73
      while (!rep(k)) {
deba@2205
    74
        k = items[k] ;
deba@2205
    75
      }
deba@2205
    76
      while (idx != k) {
deba@2205
    77
        int next = items[idx];
deba@2205
    78
        const_cast<int&>(items[idx]) = k;
deba@2205
    79
        idx = next;
deba@2205
    80
      }
deba@2205
    81
      return k;
deba@2205
    82
    }
beckerjc@483
    83
beckerjc@483
    84
  public:
beckerjc@483
    85
deba@2205
    86
    /// \brief Constructor
deba@2205
    87
    ///
deba@2205
    88
    /// Constructor of the UnionFind class. You should give an item to
deba@2205
    89
    /// integer map which will be used from the data structure. If you
deba@2205
    90
    /// modify directly this map that may cause segmentation fault,
deba@2205
    91
    /// invalid data structure, or infinite loop when you use again
deba@2205
    92
    /// the union-find.
deba@2205
    93
    UnionFind(ItemIntMap& m) : index(m) {}
beckerjc@483
    94
deba@2205
    95
    /// \brief Returns the index of the element's component.
deba@2205
    96
    ///
deba@2205
    97
    /// The method returns the index of the element's component.
deba@2205
    98
    /// This is an integer between zero and the number of inserted elements.
deba@2205
    99
    ///
deba@2205
   100
    int find(const Item& a) {
deba@2205
   101
      return repIndex(index[a]);
beckerjc@483
   102
    }
beckerjc@483
   103
deba@2427
   104
    /// \brief Clears the union-find data structure
deba@2427
   105
    ///
deba@2427
   106
    /// Erase each item from the data structure.
deba@2427
   107
    void clear() {
deba@2427
   108
      items.clear();
deba@2427
   109
    }
deba@2427
   110
deba@2205
   111
    /// \brief Inserts a new element into the structure.
deba@2205
   112
    ///
deba@2205
   113
    /// This method inserts a new element into the data structure. 
deba@2205
   114
    ///
deba@2205
   115
    /// The method returns the index of the new component.
deba@2205
   116
    int insert(const Item& a) {
deba@2205
   117
      int n = items.size();
deba@2205
   118
      items.push_back(-1);
deba@2205
   119
      index.set(a,n);
beckerjc@483
   120
      return n;
beckerjc@483
   121
    }
beckerjc@483
   122
deba@2205
   123
    /// \brief Joining the components of element \e a and element \e b.
deba@2205
   124
    ///
deba@2205
   125
    /// This is the \e union operation of the Union-Find structure. 
deba@2205
   126
    /// Joins the component of element \e a and component of
deba@2205
   127
    /// element \e b. If \e a and \e b are in the same component then
deba@2205
   128
    /// it returns false otherwise it returns true.
deba@2205
   129
    bool join(const Item& a, const Item& b) {
deba@2205
   130
      int ka = repIndex(index[a]);
deba@2205
   131
      int kb = repIndex(index[b]);
beckerjc@483
   132
deba@2205
   133
      if ( ka == kb ) 
beckerjc@483
   134
	return false;
beckerjc@483
   135
deba@2205
   136
      if (items[ka] < items[kb]) {
deba@2205
   137
	items[ka] += items[kb];
deba@2205
   138
	items[kb] = ka;
deba@2205
   139
      } else {
deba@2205
   140
	items[kb] += items[ka];
deba@2205
   141
	items[ka] = kb;
beckerjc@483
   142
      }
beckerjc@483
   143
      return true;
beckerjc@483
   144
    }
beckerjc@483
   145
deba@2205
   146
    /// \brief Returns the size of the component of element \e a.
deba@2205
   147
    ///
deba@2205
   148
    /// Returns the size of the component of element \e a.
deba@2205
   149
    int size(const Item& a) {
deba@2205
   150
      int k = repIndex(index[a]);
deba@2205
   151
      return - items[k];
beckerjc@483
   152
    }
beckerjc@483
   153
beckerjc@483
   154
  };
beckerjc@483
   155
deba@2308
   156
  /// \ingroup auxdat
deba@2308
   157
  ///
deba@2205
   158
  /// \brief A \e Union-Find data structure implementation which
deba@2205
   159
  /// is able to enumerate the components.
deba@2205
   160
  ///
deba@2205
   161
  /// The class implements a \e Union-Find data structure
deba@2205
   162
  /// which is able to enumerate the components and the items in
deba@2205
   163
  /// a component. If you don't need this feature then perhaps it's
deba@2205
   164
  /// better to use the \ref UnionFind class which is more efficient.
deba@2205
   165
  ///
deba@2205
   166
  /// The union operation uses rank heuristic, while
deba@2205
   167
  /// the find operation uses path compression.
deba@2205
   168
  ///
deba@2205
   169
  /// \pre You need to add all the elements by the \ref insert()
deba@2205
   170
  /// method.
deba@2205
   171
  ///
deba@2308
   172
  template <typename _ItemIntMap>
deba@2205
   173
  class UnionFindEnum {
deba@2205
   174
  public:
deba@2205
   175
    
deba@2205
   176
    typedef _ItemIntMap ItemIntMap;
deba@2308
   177
    typedef typename ItemIntMap::Key Item;
deba@2308
   178
deba@2205
   179
  private:
deba@2205
   180
    
deba@2205
   181
    // If the parent stores negative value for an item then that item
deba@2205
   182
    // is root item and it has -items[it].parent component size.  Else
deba@2205
   183
    // the items[it].parent contains the index of the parent.
deba@2205
   184
    //
deba@2205
   185
    // The \c nextItem and \c prevItem provides the double-linked
deba@2205
   186
    // cyclic list of one component's items. The \c prevClass and
deba@2205
   187
    // \c nextClass gives the double linked list of the representant
deba@2205
   188
    // items. 
deba@2205
   189
    struct ItemT {
deba@2205
   190
      int parent;
deba@2205
   191
      Item item;
beckerjc@483
   192
deba@2205
   193
      int nextItem, prevItem;
deba@2205
   194
      int nextClass, prevClass;
deba@2205
   195
    };
beckerjc@483
   196
deba@2205
   197
    std::vector<ItemT> items;
deba@2205
   198
    ItemIntMap& index;
beckerjc@483
   199
deba@2205
   200
    int firstClass;
beckerjc@483
   201
beckerjc@483
   202
deba@2205
   203
    bool rep(int idx) const {
deba@2205
   204
      return items[idx].parent < 0;
beckerjc@483
   205
    }
beckerjc@483
   206
deba@2205
   207
    int repIndex(int idx) const {
deba@2205
   208
      int k = idx;
deba@2205
   209
      while (!rep(k)) {
deba@2205
   210
        k = items[k].parent;
deba@2205
   211
      }
deba@2205
   212
      while (idx != k) {
deba@2205
   213
        int next = items[idx].parent;
deba@2205
   214
        const_cast<int&>(items[idx].parent) = k;
deba@2205
   215
        idx = next;
deba@2205
   216
      }
deba@2205
   217
      return k;
deba@2205
   218
    }
deba@2205
   219
deba@2205
   220
    void unlaceClass(int k) {
deba@2205
   221
      if (items[k].prevClass != -1) {
deba@2205
   222
        items[items[k].prevClass].nextClass = items[k].nextClass;
deba@2205
   223
      } else {
deba@2205
   224
        firstClass = items[k].nextClass;
deba@2205
   225
      }
deba@2205
   226
      if (items[k].nextClass != -1) {
deba@2205
   227
        items[items[k].nextClass].prevClass = items[k].prevClass;
deba@2205
   228
      }
deba@2205
   229
    } 
deba@2205
   230
deba@2205
   231
    void spliceItems(int ak, int bk) {
deba@2205
   232
      items[items[ak].prevItem].nextItem = bk;
deba@2205
   233
      items[items[bk].prevItem].nextItem = ak;
deba@2205
   234
      int tmp = items[ak].prevItem;
deba@2205
   235
      items[ak].prevItem = items[bk].prevItem;
deba@2205
   236
      items[bk].prevItem = tmp;
deba@2205
   237
        
klao@2003
   238
    }
klao@2003
   239
beckerjc@483
   240
  public:
beckerjc@483
   241
deba@2205
   242
    UnionFindEnum(ItemIntMap& _index) 
deba@2205
   243
      : items(), index(_index), firstClass(-1) {}
deba@2205
   244
    
deba@2205
   245
    /// \brief Inserts the given element into a new component.
deba@2205
   246
    ///
deba@2205
   247
    /// This method creates a new component consisting only of the
deba@2205
   248
    /// given element.
deba@2205
   249
    ///
deba@2205
   250
    void insert(const Item& item) {
deba@2205
   251
      ItemT t;
beckerjc@483
   252
deba@2205
   253
      int idx = items.size();
deba@2205
   254
      index.set(item, idx);
beckerjc@483
   255
deba@2205
   256
      t.nextItem = idx;
deba@2205
   257
      t.prevItem = idx;
deba@2205
   258
      t.item = item;
deba@2205
   259
      t.parent = -1;
deba@2205
   260
      
deba@2205
   261
      t.nextClass = firstClass;
deba@2205
   262
      if (firstClass != -1) {
deba@2205
   263
        items[firstClass].prevClass = idx;
deba@2205
   264
      }
deba@2205
   265
      t.prevClass = -1;
deba@2205
   266
      firstClass = idx;
beckerjc@483
   267
deba@2205
   268
      items.push_back(t);
beckerjc@483
   269
    }
beckerjc@483
   270
deba@2205
   271
    /// \brief Inserts the given element into the component of the others.
deba@2205
   272
    ///
deba@2205
   273
    /// This methods inserts the element \e a into the component of the
deba@2205
   274
    /// element \e comp. 
deba@2205
   275
    void insert(const Item& item, const Item& comp) {
deba@2205
   276
      int k = repIndex(index[comp]);
deba@2205
   277
      ItemT t;
beckerjc@483
   278
deba@2205
   279
      int idx = items.size();
deba@2205
   280
      index.set(item, idx);
deba@2205
   281
deba@2205
   282
      t.prevItem = k;
deba@2205
   283
      t.nextItem = items[k].nextItem;
deba@2205
   284
      items[items[k].nextItem].prevItem = idx;
deba@2205
   285
      items[k].nextItem = idx;
deba@2205
   286
deba@2205
   287
      t.item = item;
deba@2205
   288
      t.parent = k;
deba@2205
   289
deba@2205
   290
      --items[k].parent;
deba@2205
   291
deba@2205
   292
      items.push_back(t);
beckerjc@483
   293
    }
beckerjc@483
   294
deba@2427
   295
    /// \brief Clears the union-find data structure
deba@2427
   296
    ///
deba@2427
   297
    /// Erase each item from the data structure.
deba@2427
   298
    void clear() {
deba@2427
   299
      items.clear();
deba@2427
   300
      firstClass = -1;
deba@2427
   301
    }
deba@2427
   302
deba@2205
   303
    /// \brief Finds the leader of the component of the given element.
deba@2205
   304
    ///
deba@2205
   305
    /// The method returns the leader of the component of the given element.
deba@2205
   306
    const Item& find(const Item &item) const {
deba@2205
   307
      return items[repIndex(index[item])].item;
beckerjc@483
   308
    }
beckerjc@483
   309
deba@2205
   310
    /// \brief Joining the component of element \e a and element \e b.
deba@2205
   311
    ///
deba@2205
   312
    /// This is the \e union operation of the Union-Find structure. 
deba@2205
   313
    /// Joins the component of element \e a and component of
deba@2205
   314
    /// element \e b. If \e a and \e b are in the same component then
deba@2205
   315
    /// returns false else returns true.
deba@2205
   316
    bool join(const Item& a, const Item& b) {
beckerjc@483
   317
deba@2205
   318
      int ak = repIndex(index[a]);
deba@2205
   319
      int bk = repIndex(index[b]);
beckerjc@483
   320
deba@2205
   321
      if (ak == bk) {
beckerjc@483
   322
	return false;
beckerjc@483
   323
      }
beckerjc@483
   324
deba@2205
   325
      if ( items[ak].parent < items[bk].parent ) {
deba@2205
   326
        unlaceClass(bk);
deba@2205
   327
        items[ak].parent += items[bk].parent;
deba@2205
   328
	items[bk].parent = ak;
deba@2205
   329
      } else {
deba@2332
   330
        unlaceClass(ak);
deba@2205
   331
        items[bk].parent += items[ak].parent;
deba@2205
   332
	items[ak].parent = bk;
beckerjc@483
   333
      }
deba@2205
   334
      spliceItems(ak, bk);
beckerjc@483
   335
beckerjc@483
   336
      return true;
beckerjc@483
   337
    }
beckerjc@483
   338
deba@2205
   339
    /// \brief Returns the size of the component of element \e a.
deba@2205
   340
    ///
deba@2205
   341
    /// Returns the size of the component of element \e a.
deba@2205
   342
    int size(const Item &item) const {
deba@2205
   343
      return - items[repIndex(index[item])].parent;
beckerjc@483
   344
    }
beckerjc@483
   345
deba@2205
   346
    /// \brief Splits up the component of the element. 
deba@2205
   347
    ///
deba@2205
   348
    /// Splitting the component of the element into sigleton
deba@2205
   349
    /// components (component of size one).
deba@2205
   350
    void split(const Item &item) {
deba@2205
   351
      int k = repIndex(index[item]);
deba@2205
   352
      int idx = items[k].nextItem;
deba@2205
   353
      while (idx != k) {
deba@2205
   354
        int next = items[idx].nextItem;
deba@2205
   355
        
deba@2205
   356
        items[idx].parent = -1;
deba@2205
   357
        items[idx].prevItem = idx;
deba@2205
   358
        items[idx].nextItem = idx;
deba@2205
   359
        
deba@2205
   360
        items[idx].nextClass = firstClass;
deba@2205
   361
        items[firstClass].prevClass = idx;
deba@2205
   362
        firstClass = idx;
beckerjc@483
   363
deba@2205
   364
        idx = next;
beckerjc@483
   365
      }
beckerjc@483
   366
deba@2205
   367
      items[idx].parent = -1;
deba@2205
   368
      items[idx].prevItem = idx;
deba@2205
   369
      items[idx].nextItem = idx;
deba@2205
   370
      
deba@2205
   371
      items[firstClass].prevClass = -1;
beckerjc@483
   372
    }
beckerjc@483
   373
deba@2205
   374
    /// \brief Sets the given element to the leader element of its component.
deba@2205
   375
    ///
deba@2205
   376
    /// Sets the given element to the leader element of its component.
deba@2205
   377
    void makeRep(const Item &item) {
deba@2205
   378
      int nk = index[item];
deba@2205
   379
      int k = repIndex(nk);
deba@2205
   380
      if (nk == k) return;
deba@2205
   381
      
deba@2205
   382
      if (items[k].prevClass != -1) {
deba@2205
   383
        items[items[k].prevClass].nextClass = nk;
deba@2205
   384
      } else {
deba@2205
   385
        firstClass = nk;
deba@2205
   386
      }
deba@2205
   387
      if (items[k].nextClass != -1) {
deba@2205
   388
        items[items[k].nextClass].prevClass = nk;
deba@2205
   389
      }
deba@2205
   390
      
deba@2205
   391
      int idx = items[k].nextItem;
deba@2205
   392
      while (idx != k) {
deba@2205
   393
        items[idx].parent = nk;
deba@2205
   394
        idx = items[idx].nextItem;
deba@2205
   395
      }
deba@2205
   396
      
deba@2205
   397
      items[nk].parent = items[k].parent;
deba@2205
   398
      items[k].parent = nk;
beckerjc@483
   399
    }
beckerjc@483
   400
deba@2205
   401
    /// \brief Removes the given element from the structure.
deba@2205
   402
    ///
deba@2205
   403
    /// Removes the element from its component and if the component becomes
deba@2205
   404
    /// empty then removes that component from the component list.
deba@2205
   405
    ///
deba@2205
   406
    /// \warning It is an error to remove an element which is not in
deba@2205
   407
    /// the structure.
deba@2205
   408
    void erase(const Item &item) {
deba@2205
   409
      int idx = index[item];
deba@2205
   410
      if (rep(idx)) {
deba@2205
   411
        int k = idx;
deba@2205
   412
        if (items[k].parent == -1) {
deba@2205
   413
          unlaceClass(idx);
deba@2205
   414
          return;
deba@2205
   415
        } else {
deba@2205
   416
          int nk = items[k].nextItem;
deba@2205
   417
          if (items[k].prevClass != -1) {
deba@2205
   418
            items[items[k].prevClass].nextClass = nk;
deba@2205
   419
          } else {
deba@2205
   420
            firstClass = nk;
deba@2205
   421
          }
deba@2205
   422
          if (items[k].nextClass != -1) {
deba@2205
   423
            items[items[k].nextClass].prevClass = nk;
deba@2205
   424
          }
deba@2205
   425
      
deba@2386
   426
          int l = items[k].nextItem;
deba@2386
   427
          while (l != k) {
deba@2386
   428
            items[l].parent = nk;
deba@2386
   429
            l = items[l].nextItem;
deba@2205
   430
          }
deba@2205
   431
          
deba@2205
   432
          items[nk].parent = items[k].parent + 1;
deba@2205
   433
        }
deba@2205
   434
      } else {
deba@2205
   435
        
deba@2205
   436
        int k = repIndex(idx);
deba@2205
   437
        idx = items[k].nextItem;
deba@2205
   438
        while (idx != k) {
deba@2205
   439
          items[idx].parent = k;
deba@2205
   440
          idx = items[idx].nextItem;
deba@2205
   441
        }
beckerjc@483
   442
deba@2205
   443
        ++items[k].parent;
beckerjc@483
   444
      }
beckerjc@483
   445
deba@2205
   446
      idx = index[item];      
deba@2205
   447
      items[items[idx].prevItem].nextItem = items[idx].nextItem;
deba@2205
   448
      items[items[idx].nextItem].prevItem = items[idx].prevItem;
beckerjc@483
   449
deba@2205
   450
    }    
beckerjc@483
   451
deba@2205
   452
    /// \brief Moves the given element to another component.
deba@2205
   453
    ///
deba@2205
   454
    /// This method moves the element \e a from its component
deba@2205
   455
    /// to the component of \e comp.
deba@2205
   456
    /// If \e a and \e comp are in the same component then
deba@2205
   457
    /// it returns false otherwise it returns true.
deba@2205
   458
    bool move(const Item &item, const Item &comp) {
deba@2205
   459
      if (repIndex(index[item]) == repIndex(index[comp])) return false;
deba@2205
   460
      erase(item);
deba@2205
   461
      insert(item, comp);
beckerjc@483
   462
      return true;
beckerjc@483
   463
    }
beckerjc@483
   464
beckerjc@483
   465
deba@2205
   466
    /// \brief Removes the component of the given element from the structure.
deba@2205
   467
    ///
deba@2205
   468
    /// Removes the component of the given element from the structure.
deba@2205
   469
    ///
deba@2205
   470
    /// \warning It is an error to give an element which is not in the
deba@2205
   471
    /// structure.
deba@2205
   472
    void eraseClass(const Item &item) {
deba@2205
   473
      unlaceClass(repIndex(index[item]));
deba@2205
   474
    }
beckerjc@483
   475
deba@2205
   476
    /// \brief Lemon style iterator for the representant items.
deba@2205
   477
    ///
deba@2205
   478
    /// ClassIt is a lemon style iterator for the components. It iterates
deba@2205
   479
    /// on the representant items of the classes.
deba@2205
   480
    class ClassIt {
deba@2205
   481
    public:
deba@2205
   482
      /// \brief Constructor of the iterator
deba@2205
   483
      ///
deba@2205
   484
      /// Constructor of the iterator
deba@2205
   485
      ClassIt(const UnionFindEnum& ufe) : unionFind(&ufe) {
deba@2205
   486
        idx = unionFind->firstClass;
beckerjc@483
   487
      }
beckerjc@483
   488
deba@2205
   489
      /// \brief Constructor to get invalid iterator
deba@2205
   490
      ///
deba@2205
   491
      /// Constructor to get invalid iterator
deba@2205
   492
      ClassIt(Invalid) : unionFind(0), idx(-1) {}
deba@2205
   493
      
deba@2205
   494
      /// \brief Increment operator
deba@2205
   495
      ///
deba@2205
   496
      /// It steps to the next representant item.
deba@2205
   497
      ClassIt& operator++() {
deba@2205
   498
        idx = unionFind->items[idx].nextClass;
deba@2205
   499
        return *this;
deba@2205
   500
      }
deba@2205
   501
      
deba@2205
   502
      /// \brief Conversion operator
deba@2205
   503
      ///
deba@2205
   504
      /// It converts the iterator to the current representant item.
deba@2205
   505
      operator const Item&() const {
deba@2205
   506
        return unionFind->items[idx].item;
beckerjc@483
   507
      }
beckerjc@483
   508
deba@2205
   509
      /// \brief Equality operator
deba@2205
   510
      ///
deba@2205
   511
      /// Equality operator
deba@2205
   512
      bool operator==(const ClassIt& i) { 
deba@2205
   513
        return i.idx == idx;
deba@2205
   514
      }
beckerjc@483
   515
deba@2205
   516
      /// \brief Inequality operator
deba@2205
   517
      ///
deba@2205
   518
      /// Inequality operator
deba@2205
   519
      bool operator!=(const ClassIt& i) { 
deba@2205
   520
        return i.idx != idx;
klao@2003
   521
      }
beckerjc@483
   522
      
deba@2205
   523
    private:
deba@2205
   524
      const UnionFindEnum* unionFind;
deba@2205
   525
      int idx;
deba@2205
   526
    };
deba@2205
   527
deba@2205
   528
    /// \brief Lemon style iterator for the items of a component.
deba@2205
   529
    ///
deba@2205
   530
    /// ClassIt is a lemon style iterator for the components. It iterates
deba@2205
   531
    /// on the items of a class. By example if you want to iterate on
deba@2205
   532
    /// each items of each classes then you may write the next code.
deba@2205
   533
    ///\code
deba@2205
   534
    /// for (ClassIt cit(ufe); cit != INVALID; ++cit) {
deba@2205
   535
    ///   std::cout << "Class: ";
deba@2205
   536
    ///   for (ItemIt iit(ufe, cit); iit != INVALID; ++iit) {
deba@2205
   537
    ///     std::cout << toString(iit) << ' ' << std::endl;
deba@2205
   538
    ///   }
deba@2205
   539
    ///   std::cout << std::endl;
deba@2205
   540
    /// }
deba@2205
   541
    ///\endcode
deba@2205
   542
    class ItemIt {
deba@2205
   543
    public:
deba@2205
   544
      /// \brief Constructor of the iterator
deba@2205
   545
      ///
deba@2205
   546
      /// Constructor of the iterator. The iterator iterates
deba@2205
   547
      /// on the class of the \c item.
deba@2205
   548
      ItemIt(const UnionFindEnum& ufe, const Item& item) : unionFind(&ufe) {
deba@2205
   549
        idx = unionFind->repIndex(unionFind->index[item]);
beckerjc@483
   550
      }
beckerjc@483
   551
deba@2205
   552
      /// \brief Constructor to get invalid iterator
deba@2205
   553
      ///
deba@2205
   554
      /// Constructor to get invalid iterator
deba@2205
   555
      ItemIt(Invalid) : unionFind(0), idx(-1) {}
deba@2205
   556
      
deba@2205
   557
      /// \brief Increment operator
deba@2205
   558
      ///
deba@2205
   559
      /// It steps to the next item in the class.
deba@2205
   560
      ItemIt& operator++() {
deba@2205
   561
        idx = unionFind->items[idx].nextItem;
deba@2205
   562
        if (unionFind->rep(idx)) idx = -1;
deba@2205
   563
        return *this;
klao@2003
   564
      }
deba@2205
   565
      
deba@2205
   566
      /// \brief Conversion operator
deba@2205
   567
      ///
deba@2205
   568
      /// It converts the iterator to the current item.
deba@2205
   569
      operator const Item&() const {
deba@2205
   570
        return unionFind->items[idx].item;
klao@2003
   571
      }
klao@2003
   572
deba@2205
   573
      /// \brief Equality operator
deba@2205
   574
      ///
deba@2205
   575
      /// Equality operator
deba@2205
   576
      bool operator==(const ItemIt& i) { 
deba@2205
   577
        return i.idx == idx;
klao@2003
   578
      }
klao@2003
   579
deba@2205
   580
      /// \brief Inequality operator
deba@2205
   581
      ///
deba@2205
   582
      /// Inequality operator
deba@2205
   583
      bool operator!=(const ItemIt& i) { 
deba@2205
   584
        return i.idx != idx;
deba@2205
   585
      }
deba@2205
   586
      
deba@2205
   587
    private:
deba@2205
   588
      const UnionFindEnum* unionFind;
deba@2205
   589
      int idx;
beckerjc@483
   590
    };
beckerjc@483
   591
beckerjc@483
   592
  };
beckerjc@483
   593
beckerjc@483
   594
beckerjc@483
   595
  //! @}
beckerjc@483
   596
alpar@921
   597
} //namespace lemon
beckerjc@483
   598
alpar@921
   599
#endif //LEMON_UNION_FIND_H