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