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