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