lemon/unionfind.h
author deba
Tue, 30 Oct 2007 20:21:10 +0000
changeset 2505 1bb471764ab8
parent 2427 d40c31b08d6f
child 2506 216c6bd5c18c
permissions -rw-r--r--
Redesign interface of MaxMatching and UnionFindEnum
New class ExtendFindEnum

Faster MaxMatching
     1 /* -*- C++ -*-
     2  *
     3  * This file is a part of LEMON, a generic C++ optimization library
     4  *
     5  * Copyright (C) 2003-2007
     6  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     7  * (Egervary Research Group on Combinatorial Optimization, EGRES).
     8  *
     9  * Permission to use, modify and distribute this software is granted
    10  * provided that this copyright notice appears in all copies. For
    11  * precise terms see the accompanying LICENSE file.
    12  *
    13  * This software is provided "AS IS" with no warranty of any kind,
    14  * express or implied, and with no claim as to its suitability for any
    15  * purpose.
    16  *
    17  */
    18 
    19 #ifndef LEMON_UNION_FIND_H
    20 #define LEMON_UNION_FIND_H
    21 
    22 //!\ingroup auxdat
    23 //!\file
    24 //!\brief Union-Find data structures.
    25 //!
    26 
    27 #include <vector>
    28 #include <list>
    29 #include <utility>
    30 #include <algorithm>
    31 
    32 #include <lemon/bits/invalid.h>
    33 
    34 namespace lemon {
    35 
    36   /// \ingroup auxdat
    37   ///
    38   /// \brief A \e Union-Find data structure implementation
    39   ///
    40   /// The class implements the \e Union-Find data structure. 
    41   /// The union operation uses rank heuristic, while
    42   /// the find operation uses path compression.
    43   /// This is a very simple but efficient implementation, providing 
    44   /// only four methods: join (union), find, insert and size.
    45   /// For more features see the \ref UnionFindEnum class.
    46   ///
    47   /// It is primarily used in Kruskal algorithm for finding minimal
    48   /// cost spanning tree in a graph.
    49   /// \sa kruskal()
    50   ///
    51   /// \pre You need to add all the elements by the \ref insert()
    52   /// method.  
    53   template <typename _ItemIntMap>
    54   class UnionFind {
    55   public:
    56 
    57     typedef _ItemIntMap ItemIntMap;
    58     typedef typename ItemIntMap::Key Item;
    59 
    60   private:
    61     // If the items vector stores negative value for an item then
    62     // that item is root item and it has -items[it] component size.
    63     // Else the items[it] contains the index of the parent.
    64     std::vector<int> items;
    65     ItemIntMap& index;
    66 
    67     bool rep(int idx) const {
    68       return items[idx] < 0;
    69     }
    70 
    71     int repIndex(int idx) const {
    72       int k = idx;
    73       while (!rep(k)) {
    74         k = items[k] ;
    75       }
    76       while (idx != k) {
    77         int next = items[idx];
    78         const_cast<int&>(items[idx]) = k;
    79         idx = next;
    80       }
    81       return k;
    82     }
    83 
    84   public:
    85 
    86     /// \brief Constructor
    87     ///
    88     /// Constructor of the UnionFind class. You should give an item to
    89     /// integer map which will be used from the data structure. If you
    90     /// modify directly this map that may cause segmentation fault,
    91     /// invalid data structure, or infinite loop when you use again
    92     /// the union-find.
    93     UnionFind(ItemIntMap& m) : index(m) {}
    94 
    95     /// \brief Returns the index of the element's component.
    96     ///
    97     /// The method returns the index of the element's component.
    98     /// This is an integer between zero and the number of inserted elements.
    99     ///
   100     int find(const Item& a) {
   101       return repIndex(index[a]);
   102     }
   103 
   104     /// \brief Clears the union-find data structure
   105     ///
   106     /// Erase each item from the data structure.
   107     void clear() {
   108       items.clear();
   109     }
   110 
   111     /// \brief Inserts a new element into the structure.
   112     ///
   113     /// This method inserts a new element into the data structure. 
   114     ///
   115     /// The method returns the index of the new component.
   116     int insert(const Item& a) {
   117       int n = items.size();
   118       items.push_back(-1);
   119       index.set(a,n);
   120       return n;
   121     }
   122 
   123     /// \brief Joining the components of element \e a and element \e b.
   124     ///
   125     /// This is the \e union operation of the Union-Find structure. 
   126     /// Joins the component of element \e a and component of
   127     /// element \e b. If \e a and \e b are in the same component then
   128     /// it returns false otherwise it returns true.
   129     bool join(const Item& a, const Item& b) {
   130       int ka = repIndex(index[a]);
   131       int kb = repIndex(index[b]);
   132 
   133       if ( ka == kb ) 
   134 	return false;
   135 
   136       if (items[ka] < items[kb]) {
   137 	items[ka] += items[kb];
   138 	items[kb] = ka;
   139       } else {
   140 	items[kb] += items[ka];
   141 	items[ka] = kb;
   142       }
   143       return true;
   144     }
   145 
   146     /// \brief Returns the size of the component of element \e a.
   147     ///
   148     /// Returns the size of the component of element \e a.
   149     int size(const Item& a) {
   150       int k = repIndex(index[a]);
   151       return - items[k];
   152     }
   153 
   154   };
   155 
   156   /// \ingroup auxdat
   157   ///
   158   /// \brief A \e Union-Find data structure implementation which
   159   /// is able to enumerate the components.
   160   ///
   161   /// The class implements a \e Union-Find data structure
   162   /// which is able to enumerate the components and the items in
   163   /// a component. If you don't need this feature then perhaps it's
   164   /// better to use the \ref UnionFind class which is more efficient.
   165   ///
   166   /// The union operation uses rank heuristic, while
   167   /// the find operation uses path compression.
   168   ///
   169   /// \pre You need to add all the elements by the \ref insert()
   170   /// method.
   171   ///
   172   template <typename _ItemIntMap>
   173   class UnionFindEnum {
   174   public:
   175     
   176     typedef _ItemIntMap ItemIntMap;
   177     typedef typename ItemIntMap::Key Item;
   178 
   179   private:
   180     
   181     ItemIntMap& index;
   182 
   183     // If the parent stores negative value for an item then that item
   184     // is root item and it has ~(items[it].parent) component id.  Else
   185     // the items[it].parent contains the index of the parent.
   186     //
   187     // The \c next and \c prev provides the double-linked
   188     // cyclic list of one component's items.
   189     struct ItemT {
   190       int parent;
   191       Item item;
   192 
   193       int next, prev;
   194     };
   195 
   196     std::vector<ItemT> items;
   197     int firstFreeItem;
   198 
   199     struct ClassT {
   200       int size;
   201       int firstItem;
   202       int next, prev;
   203     };
   204     
   205     std::vector<ClassT> classes;
   206     int firstClass, firstFreeClass;
   207 
   208     int newClass() {
   209       if (firstFreeClass == -1) {
   210 	int cdx = classes.size();
   211 	classes.push_back(ClassT());
   212 	return cdx;
   213       } else {
   214 	int cdx = firstFreeClass;
   215 	firstFreeClass = classes[firstFreeClass].next;
   216 	return cdx;
   217       }
   218     }
   219 
   220     int newItem() {
   221       if (firstFreeItem == -1) {
   222 	int idx = items.size();
   223 	items.push_back(ItemT());
   224 	return idx;
   225       } else {
   226 	int idx = firstFreeItem;
   227 	firstFreeItem = items[firstFreeItem].next;
   228 	return idx;
   229       }
   230     }
   231 
   232 
   233     bool rep(int idx) const {
   234       return items[idx].parent < 0;
   235     }
   236 
   237     int repIndex(int idx) const {
   238       int k = idx;
   239       while (!rep(k)) {
   240         k = items[k].parent;
   241       }
   242       while (idx != k) {
   243         int next = items[idx].parent;
   244         const_cast<int&>(items[idx].parent) = k;
   245         idx = next;
   246       }
   247       return k;
   248     }
   249 
   250     int classIndex(int idx) const {
   251       return ~(items[repIndex(idx)].parent);
   252     }
   253 
   254     void singletonItem(int idx) {
   255       items[idx].next = idx;
   256       items[idx].prev = idx;
   257     }
   258 
   259     void laceItem(int idx, int rdx) {
   260       items[idx].prev = rdx;
   261       items[idx].next = items[rdx].next;
   262       items[items[rdx].next].prev = idx;
   263       items[rdx].next = idx;
   264     }
   265 
   266     void unlaceItem(int idx) {
   267       items[items[idx].prev].next = items[idx].next;
   268       items[items[idx].next].prev = items[idx].prev;
   269       
   270       items[idx].next = firstFreeItem;
   271       firstFreeItem = idx;
   272     }
   273 
   274     void spliceItems(int ak, int bk) {
   275       items[items[ak].prev].next = bk;
   276       items[items[bk].prev].next = ak;
   277       int tmp = items[ak].prev;
   278       items[ak].prev = items[bk].prev;
   279       items[bk].prev = tmp;
   280         
   281     }
   282 
   283     void laceClass(int cls) {
   284       if (firstClass != -1) {
   285         classes[firstClass].prev = cls;
   286       }
   287       classes[cls].next = firstClass;
   288       classes[cls].prev = -1;
   289       firstClass = cls;
   290     } 
   291 
   292     void unlaceClass(int cls) {
   293       if (classes[cls].prev != -1) {
   294         classes[classes[cls].prev].next = classes[cls].next;
   295       } else {
   296         firstClass = classes[cls].next;
   297       }
   298       if (classes[cls].next != -1) {
   299         classes[classes[cls].next].prev = classes[cls].prev;
   300       }
   301       
   302       classes[cls].next = firstFreeClass;
   303       firstFreeClass = cls;
   304     } 
   305 
   306   public:
   307 
   308     UnionFindEnum(ItemIntMap& _index) 
   309       : index(_index), items(), firstFreeItem(-1), 
   310 	firstClass(-1), firstFreeClass(-1) {}
   311     
   312     /// \brief Inserts the given element into a new component.
   313     ///
   314     /// This method creates a new component consisting only of the
   315     /// given element.
   316     ///
   317     int insert(const Item& item) {
   318       int idx = newItem();
   319 
   320       index.set(item, idx);
   321 
   322       singletonItem(idx);
   323       items[idx].item = item;
   324 
   325       int cdx = newClass();
   326 
   327       items[idx].parent = ~cdx;
   328 
   329       laceClass(cdx);
   330       classes[cdx].size = 1;
   331       classes[cdx].firstItem = idx;
   332 
   333       firstClass = cdx;
   334       
   335       return cdx;
   336     }
   337 
   338     /// \brief Inserts the given element into the component of the others.
   339     ///
   340     /// This methods inserts the element \e a into the component of the
   341     /// element \e comp. 
   342     void insert(const Item& item, int cls) {
   343       int rdx = classes[cls].firstItem;
   344       int idx = newItem();
   345 
   346       index.set(item, idx);
   347 
   348       laceItem(idx, rdx);
   349 
   350       items[idx].item = item;
   351       items[idx].parent = rdx;
   352 
   353       ++classes[~(items[rdx].parent)].size;
   354     }
   355 
   356     /// \brief Clears the union-find data structure
   357     ///
   358     /// Erase each item from the data structure.
   359     void clear() {
   360       items.clear();
   361       firstClass = -1;
   362       firstFreeItem = -1;
   363     }
   364 
   365     /// \brief Finds the component of the given element.
   366     ///
   367     /// The method returns the component id of the given element.
   368     int find(const Item &item) const {
   369       return ~(items[repIndex(index[item])].parent);
   370     }
   371 
   372     /// \brief Joining the component of element \e a and element \e b.
   373     ///
   374     /// This is the \e union operation of the Union-Find structure. 
   375     /// Joins the component of element \e a and component of
   376     /// element \e b. If \e a and \e b are in the same component then
   377     /// returns -1 else returns the remaining class.
   378     int join(const Item& a, const Item& b) {
   379 
   380       int ak = repIndex(index[a]);
   381       int bk = repIndex(index[b]);
   382 
   383       if (ak == bk) {
   384 	return -1;
   385       }
   386 
   387       int acx = ~(items[ak].parent);
   388       int bcx = ~(items[bk].parent);
   389 
   390       int rcx;
   391 
   392       if (classes[acx].size > classes[bcx].size) {
   393 	classes[acx].size += classes[bcx].size;
   394 	items[bk].parent = ak;
   395         unlaceClass(bcx);
   396 	rcx = acx;
   397       } else {
   398 	classes[bcx].size += classes[acx].size;
   399 	items[ak].parent = bk;
   400         unlaceClass(acx);
   401 	rcx = bcx;
   402       }
   403       spliceItems(ak, bk);
   404 
   405       return rcx;
   406     }
   407 
   408     /// \brief Returns the size of the class.
   409     ///
   410     /// Returns the size of the class.
   411     int size(int cls) const {
   412       return classes[cls].size;
   413     }
   414 
   415     /// \brief Splits up the component. 
   416     ///
   417     /// Splitting the component into singleton components (component
   418     /// of size one).
   419     void split(int cls) {
   420       int fdx = classes[cls].firstItem;
   421       int idx = items[fdx].next;
   422       while (idx != fdx) {
   423         int next = items[idx].next;
   424 
   425 	singletonItem(idx);
   426 
   427 	int cdx = newClass();        
   428         items[idx].parent = ~cdx;
   429 
   430 	laceClass(cdx);
   431 	classes[cdx].size = 1;
   432 	classes[cdx].firstItem = idx;
   433         
   434         idx = next;
   435       }
   436 
   437       items[idx].prev = idx;
   438       items[idx].next = idx;
   439 
   440       classes[~(items[idx].parent)].size = 1;
   441       
   442     }
   443 
   444     /// \brief Removes the given element from the structure.
   445     ///
   446     /// Removes the element from its component and if the component becomes
   447     /// empty then removes that component from the component list.
   448     ///
   449     /// \warning It is an error to remove an element which is not in
   450     /// the structure.
   451     /// \warning This running time of this operation is proportional to the
   452     /// number of the items in this class.
   453     void erase(const Item& item) {
   454       int idx = index[item];
   455       int fdx = items[idx].next;
   456 
   457       int cdx = classIndex(idx);
   458       if (idx == fdx) {
   459 	unlaceClass(cdx);
   460 	items[idx].next = firstFreeItem;
   461 	firstFreeItem = idx;
   462 	return;
   463       } else {
   464 	classes[cdx].firstItem = fdx;
   465 	--classes[cdx].size;
   466 	items[fdx].parent = ~cdx;
   467 
   468 	unlaceItem(idx);
   469 	idx = items[fdx].next;
   470 	while (idx != fdx) {
   471 	  items[idx].parent = fdx;
   472 	  idx = items[idx].next;
   473 	}
   474           
   475       }
   476 
   477     }    
   478 
   479     /// \brief Removes the component of the given element from the structure.
   480     ///
   481     /// Removes the component of the given element from the structure.
   482     ///
   483     /// \warning It is an error to give an element which is not in the
   484     /// structure.
   485     void eraseClass(int cls) {
   486       int fdx = classes[cls].firstItem;
   487       unlaceClass(cls);
   488       items[items[fdx].prev].next = firstFreeItem;
   489       firstFreeItem = fdx;
   490     }
   491 
   492     /// \brief Lemon style iterator for the representant items.
   493     ///
   494     /// ClassIt is a lemon style iterator for the components. It iterates
   495     /// on the ids of the classes.
   496     class ClassIt {
   497     public:
   498       /// \brief Constructor of the iterator
   499       ///
   500       /// Constructor of the iterator
   501       ClassIt(const UnionFindEnum& ufe) : unionFind(&ufe) {
   502         cdx = unionFind->firstClass;
   503       }
   504 
   505       /// \brief Constructor to get invalid iterator
   506       ///
   507       /// Constructor to get invalid iterator
   508       ClassIt(Invalid) : unionFind(0), cdx(-1) {}
   509       
   510       /// \brief Increment operator
   511       ///
   512       /// It steps to the next representant item.
   513       ClassIt& operator++() {
   514         cdx = unionFind->classes[cdx].next;
   515         return *this;
   516       }
   517       
   518       /// \brief Conversion operator
   519       ///
   520       /// It converts the iterator to the current representant item.
   521       operator int() const {
   522         return cdx;
   523       }
   524 
   525       /// \brief Equality operator
   526       ///
   527       /// Equality operator
   528       bool operator==(const ClassIt& i) { 
   529         return i.cdx == cdx;
   530       }
   531 
   532       /// \brief Inequality operator
   533       ///
   534       /// Inequality operator
   535       bool operator!=(const ClassIt& i) { 
   536         return i.cdx != cdx;
   537       }
   538       
   539     private:
   540       const UnionFindEnum* unionFind;
   541       int cdx;
   542     };
   543 
   544     /// \brief Lemon style iterator for the items of a component.
   545     ///
   546     /// ClassIt is a lemon style iterator for the components. It iterates
   547     /// on the items of a class. By example if you want to iterate on
   548     /// each items of each classes then you may write the next code.
   549     ///\code
   550     /// for (ClassIt cit(ufe); cit != INVALID; ++cit) {
   551     ///   std::cout << "Class: ";
   552     ///   for (ItemIt iit(ufe, cit); iit != INVALID; ++iit) {
   553     ///     std::cout << toString(iit) << ' ' << std::endl;
   554     ///   }
   555     ///   std::cout << std::endl;
   556     /// }
   557     ///\endcode
   558     class ItemIt {
   559     public:
   560       /// \brief Constructor of the iterator
   561       ///
   562       /// Constructor of the iterator. The iterator iterates
   563       /// on the class of the \c item.
   564       ItemIt(const UnionFindEnum& ufe, int cls) : unionFind(&ufe) {
   565         fdx = idx = unionFind->classes[cls].firstItem;
   566       }
   567 
   568       /// \brief Constructor to get invalid iterator
   569       ///
   570       /// Constructor to get invalid iterator
   571       ItemIt(Invalid) : unionFind(0), idx(-1) {}
   572       
   573       /// \brief Increment operator
   574       ///
   575       /// It steps to the next item in the class.
   576       ItemIt& operator++() {
   577         idx = unionFind->items[idx].next;
   578         if (idx == fdx) idx = -1;
   579         return *this;
   580       }
   581       
   582       /// \brief Conversion operator
   583       ///
   584       /// It converts the iterator to the current item.
   585       operator const Item&() const {
   586         return unionFind->items[idx].item;
   587       }
   588 
   589       /// \brief Equality operator
   590       ///
   591       /// Equality operator
   592       bool operator==(const ItemIt& i) { 
   593         return i.idx == idx;
   594       }
   595 
   596       /// \brief Inequality operator
   597       ///
   598       /// Inequality operator
   599       bool operator!=(const ItemIt& i) { 
   600         return i.idx != idx;
   601       }
   602       
   603     private:
   604       const UnionFindEnum* unionFind;
   605       int idx, fdx;
   606     };
   607 
   608   };
   609 
   610   /// \ingroup auxdat
   611   ///
   612   /// \brief A \e Extend-Find data structure implementation which
   613   /// is able to enumerate the components.
   614   ///
   615   /// The class implements an \e Extend-Find data structure which is
   616   /// able to enumerate the components and the items in a
   617   /// component. The data structure is a simplification of the
   618   /// Union-Find structure, and it does not allow to merge two components.
   619   ///
   620   /// \pre You need to add all the elements by the \ref insert()
   621   /// method.
   622   template <typename _ItemIntMap>
   623   class ExtendFindEnum {
   624   public:
   625     
   626     typedef _ItemIntMap ItemIntMap;
   627     typedef typename ItemIntMap::Key Item;
   628 
   629   private:
   630     
   631     ItemIntMap& index;
   632 
   633     struct ItemT {
   634       int cls;
   635       Item item;
   636       int next, prev;
   637     };
   638 
   639     std::vector<ItemT> items;
   640     int firstFreeItem;
   641 
   642     struct ClassT {
   643       int firstItem;
   644       int next, prev;
   645     };
   646 
   647     std::vector<ClassT> classes;
   648 
   649     int firstClass, firstFreeClass;
   650 
   651     int newClass() {
   652       if (firstFreeClass != -1) {
   653 	int cdx = firstFreeClass;
   654 	firstFreeClass = classes[cdx].next;
   655 	return cdx;
   656       } else {
   657 	classes.push_back(ClassT());
   658 	return classes.size() - 1;
   659       }
   660     }
   661 
   662     int newItem() {
   663       if (firstFreeItem != -1) {
   664 	int idx = firstFreeItem;
   665 	firstFreeItem = items[idx].next;
   666 	return idx;
   667       } else {
   668 	items.push_back(ItemT());
   669 	return items.size() - 1;
   670       }
   671     }
   672 
   673   public:
   674 
   675     /// \brief Constructor
   676     ExtendFindEnum(ItemIntMap& _index) 
   677       : index(_index), items(), firstFreeItem(-1), 
   678 	classes(), firstClass(-1), firstFreeClass(-1) {}
   679     
   680     /// \brief Inserts the given element into a new component.
   681     ///
   682     /// This method creates a new component consisting only of the
   683     /// given element.
   684     int insert(const Item& item) {
   685       int cdx = newClass();
   686       classes[cdx].prev = -1;
   687       classes[cdx].next = firstClass;
   688       firstClass = cdx;
   689       
   690       int idx = newItem();
   691       items[idx].item = item;
   692       items[idx].cls = cdx;
   693       items[idx].prev = idx;
   694       items[idx].next = idx;
   695 
   696       classes[cdx].firstItem = idx;
   697 
   698       index.set(item, idx);
   699       
   700       return cdx;
   701     }
   702 
   703     /// \brief Inserts the given element into the given component.
   704     ///
   705     /// This methods inserts the element \e item a into the \e cls class.
   706     void insert(const Item& item, int cls) {
   707       int idx = newItem();
   708       int rdx = classes[cls].firstItem;
   709       items[idx].item = item;
   710       items[idx].cls = cls;
   711 
   712       items[idx].prev = rdx;
   713       items[idx].next = items[rdx].next;
   714       items[items[rdx].next].prev = idx;
   715       items[rdx].next = idx;
   716 
   717       index.set(item, idx);
   718     }
   719 
   720     /// \brief Clears the union-find data structure
   721     ///
   722     /// Erase each item from the data structure.
   723     void clear() {
   724       items.clear();
   725       classes.clear;
   726       firstClass = firstFreeClass = firstFreeItem = -1;
   727     }
   728 
   729     /// \brief Gives back the class of the \e item.
   730     ///
   731     /// Gives back the class of the \e item.
   732     int find(const Item &item) const {
   733       return items[index[item]].cls;
   734     }
   735     
   736     /// \brief Removes the given element from the structure.
   737     ///
   738     /// Removes the element from its component and if the component becomes
   739     /// empty then removes that component from the component list.
   740     ///
   741     /// \warning It is an error to remove an element which is not in
   742     /// the structure.
   743     void erase(const Item &item) {
   744       int idx = index[item];
   745       int cdx = items[idx].cls;
   746       
   747       if (idx == items[idx].next) {
   748 	if (classes[cdx].prev != -1) {
   749 	  classes[classes[cdx].prev].next = classes[cdx].next; 
   750 	} else {
   751 	  firstClass = classes[cdx].next;
   752 	}
   753 	if (classes[cdx].next != -1) {
   754 	  classes[classes[cdx].next].prev = classes[cdx].prev; 
   755 	}
   756 	classes[cdx].next = firstFreeClass;
   757 	firstFreeClass = cdx;
   758       } else {
   759 	classes[cdx].firstItem = items[idx].next;
   760 	items[items[idx].next].prev = items[idx].prev;
   761 	items[items[idx].prev].next = items[idx].next;
   762       }
   763       items[idx].next = firstFreeItem;
   764       firstFreeItem = idx;
   765 	
   766     }    
   767 
   768     
   769     /// \brief Removes the component of the given element from the structure.
   770     ///
   771     /// Removes the component of the given element from the structure.
   772     ///
   773     /// \warning It is an error to give an element which is not in the
   774     /// structure.
   775     void eraseClass(int cdx) {
   776       int idx = classes[cdx].firstItem;
   777       items[items[idx].prev].next = firstFreeItem;
   778       firstFreeItem = idx;
   779 
   780       if (classes[cdx].prev != -1) {
   781 	classes[classes[cdx].prev].next = classes[cdx].next; 
   782       } else {
   783 	firstClass = classes[cdx].next;
   784       }
   785       if (classes[cdx].next != -1) {
   786 	classes[classes[cdx].next].prev = classes[cdx].prev; 
   787       }
   788       classes[cdx].next = firstFreeClass;
   789       firstFreeClass = cdx;
   790     }
   791 
   792     /// \brief Lemon style iterator for the classes.
   793     ///
   794     /// ClassIt is a lemon style iterator for the components. It iterates
   795     /// on the ids of classes.
   796     class ClassIt {
   797     public:
   798       /// \brief Constructor of the iterator
   799       ///
   800       /// Constructor of the iterator
   801       ClassIt(const ExtendFindEnum& ufe) : extendFind(&ufe) {
   802         cdx = extendFind->firstClass;
   803       }
   804 
   805       /// \brief Constructor to get invalid iterator
   806       ///
   807       /// Constructor to get invalid iterator
   808       ClassIt(Invalid) : extendFind(0), cdx(-1) {}
   809       
   810       /// \brief Increment operator
   811       ///
   812       /// It steps to the next representant item.
   813       ClassIt& operator++() {
   814         cdx = extendFind->classes[cdx].next;
   815         return *this;
   816       }
   817       
   818       /// \brief Conversion operator
   819       ///
   820       /// It converts the iterator to the current class id.
   821       operator int() const {
   822         return cdx;
   823       }
   824 
   825       /// \brief Equality operator
   826       ///
   827       /// Equality operator
   828       bool operator==(const ClassIt& i) { 
   829         return i.cdx == cdx;
   830       }
   831 
   832       /// \brief Inequality operator
   833       ///
   834       /// Inequality operator
   835       bool operator!=(const ClassIt& i) { 
   836         return i.cdx != cdx;
   837       }
   838       
   839     private:
   840       const ExtendFindEnum* extendFind;
   841       int cdx;
   842     };
   843 
   844     /// \brief Lemon style iterator for the items of a component.
   845     ///
   846     /// ClassIt is a lemon style iterator for the components. It iterates
   847     /// on the items of a class. By example if you want to iterate on
   848     /// each items of each classes then you may write the next code.
   849     ///\code
   850     /// for (ClassIt cit(ufe); cit != INVALID; ++cit) {
   851     ///   std::cout << "Class: ";
   852     ///   for (ItemIt iit(ufe, cit); iit != INVALID; ++iit) {
   853     ///     std::cout << toString(iit) << ' ' << std::endl;
   854     ///   }
   855     ///   std::cout << std::endl;
   856     /// }
   857     ///\endcode
   858     class ItemIt {
   859     public:
   860       /// \brief Constructor of the iterator
   861       ///
   862       /// Constructor of the iterator. The iterator iterates
   863       /// on the class of the \c item.
   864       ItemIt(const ExtendFindEnum& ufe, int cls) : extendFind(&ufe) {
   865         fdx = idx = extendFind->classes[cls].firstItem;
   866       }
   867 
   868       /// \brief Constructor to get invalid iterator
   869       ///
   870       /// Constructor to get invalid iterator
   871       ItemIt(Invalid) : extendFind(0), idx(-1) {}
   872       
   873       /// \brief Increment operator
   874       ///
   875       /// It steps to the next item in the class.
   876       ItemIt& operator++() {
   877         idx = extendFind->items[idx].next;
   878 	if (fdx == idx) idx = -1;
   879         return *this;
   880       }
   881       
   882       /// \brief Conversion operator
   883       ///
   884       /// It converts the iterator to the current item.
   885       operator const Item&() const {
   886         return extendFind->items[idx].item;
   887       }
   888 
   889       /// \brief Equality operator
   890       ///
   891       /// Equality operator
   892       bool operator==(const ItemIt& i) { 
   893         return i.idx == idx;
   894       }
   895 
   896       /// \brief Inequality operator
   897       ///
   898       /// Inequality operator
   899       bool operator!=(const ItemIt& i) { 
   900         return i.idx != idx;
   901       }
   902       
   903     private:
   904       const ExtendFindEnum* extendFind;
   905       int idx, fdx;
   906     };
   907 
   908   };
   909 
   910   //! @}
   911 
   912 } //namespace lemon
   913 
   914 #endif //LEMON_UNION_FIND_H