Doc for the union-find structures.
authorbeckerjc
Wed, 28 Apr 2004 20:55:18 +0000
changeset 4620ab31578af67
parent 461 a11ddf8a6614
child 463 7f3ef3009dd3
Doc for the union-find structures.
doc/Doxyfile
src/work/johanna/unionfind.h
src/work/johanna/unionfind_test.cc
     1.1 --- a/doc/Doxyfile	Wed Apr 28 16:25:34 2004 +0000
     1.2 +++ b/doc/Doxyfile	Wed Apr 28 20:55:18 2004 +0000
     1.3 @@ -405,6 +405,7 @@
     1.4                           ../src/work/alpar/list_graph.h \
     1.5                           ../src/work/athos/minlengthpaths.h \
     1.6                           ../src/work/klao/path.h \
     1.7 +                         ../src/work/johanna/unionfind.h \
     1.8  			 ../src/work/marci/graph_wrapper.h	
     1.9                           
    1.10  
     2.1 --- a/src/work/johanna/unionfind.h	Wed Apr 28 16:25:34 2004 +0000
     2.2 +++ b/src/work/johanna/unionfind.h	Wed Apr 28 20:55:18 2004 +0000
     2.3 @@ -2,6 +2,11 @@
     2.4  #ifndef HUGO_UNION_FIND_H
     2.5  #define HUGO_UNION_FIND_H
     2.6  
     2.7 +//!ingroup auxdat
     2.8 +//!\file
     2.9 +//!\brief Union-Find data structures.
    2.10 +
    2.11 +
    2.12  #include <vector>
    2.13  #include <list>
    2.14  #include <utility>
    2.15 @@ -11,6 +16,24 @@
    2.16  
    2.17  namespace hugo {
    2.18  
    2.19 +  //! \addtogroup auxdat
    2.20 +  //! @{
    2.21 +
    2.22 +  /**
    2.23 +   * \brief A \e Union-Find data structure implementation
    2.24 +   *
    2.25 +   * The class implements the \e Union-Find data structure. 
    2.26 +   * The union operation uses rank heuristic, while
    2.27 +   * the find operation uses path compresson.
    2.28 +   * This is a very simple but efficient implementation, providing 
    2.29 +   * only four methods: join (union), find, insert and size.
    2.30 +   * For more features see the \ref UnionFindEnum class.
    2.31 +   *
    2.32 +   * \pre The elements are automatically added only if the map 
    2.33 +   * given to the constructor was filled with -1's. Otherwise you
    2.34 +   * need to add all the elements by the \ref insert() method.
    2.35 +   */
    2.36 +
    2.37    template <typename T, typename TIntMap>
    2.38    class UnionFind {
    2.39      
    2.40 @@ -25,6 +48,12 @@
    2.41    public:
    2.42      UnionFind(TIntMap& m) : map(m) {}
    2.43  
    2.44 +    /**
    2.45 +     * \brief Returns the index of the element's component.
    2.46 +     *
    2.47 +     * The method returns the index of the element's component.
    2.48 +     * This is an integer between zero and the number of inserted elements.
    2.49 +     */
    2.50  
    2.51      int find(T a)
    2.52      {
    2.53 @@ -45,6 +74,19 @@
    2.54        return comp;
    2.55      }
    2.56  
    2.57 +    /**
    2.58 +     * \brief Insert a new element into the structure.
    2.59 +     *
    2.60 +     * This method inserts a new element into the data structure. 
    2.61 +     *
    2.62 +     * It is not required to use this method:
    2.63 +     * if the map given to the constructor was filled 
    2.64 +     * with -1's then it is called automatically
    2.65 +     * on the first \ref find or \ref join.
    2.66 +     *
    2.67 +     * The method returns the index of the new component.
    2.68 +     */
    2.69 +
    2.70      int insert(T a)
    2.71      {
    2.72        int n = data.size();
    2.73 @@ -53,6 +95,15 @@
    2.74        return n;
    2.75      }
    2.76  
    2.77 +    /**
    2.78 +     * \brief Joining the components of element \e a and element \e b.
    2.79 +     *
    2.80 +     * This is the \e union operation of the Union-Find structure. 
    2.81 +     * Joins the component of elemenent \e a and component of
    2.82 +     * element \e b. If \e a and \e b are in the same component then
    2.83 +     * it returns false otherwise it returns true.
    2.84 +     */
    2.85 +
    2.86      bool join(T a, T b)
    2.87      {
    2.88        int ca = find(a);
    2.89 @@ -72,6 +123,12 @@
    2.90        return true;
    2.91      }
    2.92  
    2.93 +    /**
    2.94 +     * \brief Returns the size of the component of element \e a.
    2.95 +     *
    2.96 +     * Returns the size of the component of element \e a.
    2.97 +     */
    2.98 +
    2.99      int size(T a)
   2.100      {
   2.101        int ca = find(a);
   2.102 @@ -86,6 +143,27 @@
   2.103    /*******************************************************/
   2.104  
   2.105  
   2.106 +#ifdef DEVELOPMENT_DOCS
   2.107 +
   2.108 +  /**
   2.109 +   * \brief The auxiliary class for the \ref UnionFindEnum class.
   2.110 +   *
   2.111 +   * In the \ref UnionFindEnum class all components are represented as
   2.112 +   * a std::list. 
   2.113 +   * Items of these lists are UnionFindEnumItem structures.
   2.114 +   *
   2.115 +   * The class has four fields:
   2.116 +   *  - T me - the actual element 
   2.117 +   *  - IIter parent - the parent of the element in the union-find structure
   2.118 +   *  - int size - the size of the component of the element. 
   2.119 +   *            Only valid if the element
   2.120 +   *            is the leader of the component.
   2.121 +   *  - CIter my_class - pointer into the list of components 
   2.122 +   *            pointing to the component of the element.
   2.123 +   *            Only valid if the element is the leader of the component.
   2.124 +   */
   2.125 +
   2.126 +#endif
   2.127  
   2.128    template <typename T>
   2.129    struct UnionFindEnumItem {
   2.130 @@ -105,6 +183,24 @@
   2.131        me(_me), size(1), my_class(_my_class) {}
   2.132    };
   2.133  
   2.134 +
   2.135 +  /**
   2.136 +   * \brief A \e Union-Find data structure implementation which
   2.137 +   * is able to enumerate the components.
   2.138 +   *
   2.139 +   * The class implements an \e Union-Find data structure
   2.140 +   * which is able to enumerate the components and the items in
   2.141 +   * a component. If you don't need this feature then perhaps it's
   2.142 +   * better to use the \ref UnionFind class which is more efficient.
   2.143 +   *
   2.144 +   * The union operation uses rank heuristic, while
   2.145 +   * the find operation uses path compresson.
   2.146 +   *
   2.147 +   * \pre You
   2.148 +   * need to add all the elements by the \ref insert() method.
   2.149 +   */
   2.150 +
   2.151 +
   2.152    template <typename T, template <typename Item> class Map>
   2.153    class UnionFindEnum {
   2.154  
   2.155 @@ -124,10 +220,6 @@
   2.156      MapType& m;
   2.157      ClassList classes;
   2.158  
   2.159 -    //    IIter where(const T &a) { return m[a]; }
   2.160 -    //    IIter parent(IIter a) { return a->parent; }
   2.161 -    //    P sibling(P a) { return &m[a->sibling]; }
   2.162 -
   2.163      IIter _find(IIter a) const {
   2.164        IIter comp = a;
   2.165        IIter next;
   2.166 @@ -146,6 +238,14 @@
   2.167    public:
   2.168      UnionFindEnum(MapType& _m) : m(_m) {}
   2.169  
   2.170 +
   2.171 +    /**
   2.172 +     * \brief Insert the given element into a new component.
   2.173 +     *
   2.174 +     * This method creates a new component consisting only of the
   2.175 +     * given element.
   2.176 +     */
   2.177 +
   2.178      void insert(const T &a)
   2.179      {
   2.180  
   2.181 @@ -163,10 +263,26 @@
   2.182  
   2.183      }
   2.184  
   2.185 +    /**
   2.186 +     * \brief Find the leader of the component of the given element.
   2.187 +     *
   2.188 +     * The method returns the leader of the component of the given element.
   2.189 +     */
   2.190 +
   2.191      T find(const T &a) const {
   2.192        return _find(m[a])->me;
   2.193      }
   2.194  
   2.195 +
   2.196 +    /**
   2.197 +     * \brief Joining the component of element \e a and element \e b.
   2.198 +     *
   2.199 +     * This is the \e union operation of the Union-Find structure. 
   2.200 +     * Joins the component of elemenent \e a and component of
   2.201 +     * element \e b. If \e a and \e b are in the same component then
   2.202 +     * returns false else returns true.
   2.203 +     */
   2.204 +
   2.205      bool join(T a, T b) {
   2.206  
   2.207        IIter ca = _find(m[a]);
   2.208 @@ -202,11 +318,25 @@
   2.209        return true;
   2.210      }
   2.211  
   2.212 +
   2.213 +    /**
   2.214 +     * \brief Returns the size of the component of element \e a.
   2.215 +     *
   2.216 +     * Returns the size of the component of element \e a.
   2.217 +     */
   2.218 +
   2.219      int size(const T &a) const {
   2.220        return _find(m[a])->size;
   2.221      }
   2.222  
   2.223 -    
   2.224 +
   2.225 +    /**
   2.226 +     * \brief Split up the component of the element. 
   2.227 +     *
   2.228 +     * Splitting the component of the element into sigleton
   2.229 +     * components (component of size one).
   2.230 +     */
   2.231 +
   2.232      void split(const T &a) {
   2.233  
   2.234        IIter ca = _find(m[a]);
   2.235 @@ -230,6 +360,40 @@
   2.236        return;
   2.237      }
   2.238  
   2.239 +
   2.240 +    /**
   2.241 +     * \brief Set the given element to the leader element of its component.
   2.242 +     *
   2.243 +     * Set the given element to the leader element of its component.
   2.244 +     */
   2.245 +
   2.246 +    void makeRep(const T &a) {
   2.247 +
   2.248 +      IIter ia = m[a];
   2.249 +      IIter la = _find(ia);
   2.250 +      if (la == ia) return;
   2.251 +
   2.252 +      ia->my_class = la->my_class;
   2.253 +      la->my_class = 0;
   2.254 +
   2.255 +      ia->size = la->size;
   2.256 +
   2.257 +      CIter l = ia->my_class;
   2.258 +      l->splice(l->begin(),*l,ia);
   2.259 +
   2.260 +      ia->parent = ia;
   2.261 +      la->parent = ia;
   2.262 +    }
   2.263 +
   2.264 +
   2.265 +    /**
   2.266 +     * \brief Remove the given element from the structure.
   2.267 +     *
   2.268 +     * Remove the given element from the structure.
   2.269 +     *
   2.270 +     * Removes the element from its component and if the component becomes
   2.271 +     * empty then removes that component from the component list.
   2.272 +     */
   2.273      void erase(const T &a) {
   2.274  
   2.275        IIter ma = m[a];
   2.276 @@ -243,7 +407,7 @@
   2.277  	  return;
   2.278  	}
   2.279  	++la;
   2.280 -	la->size = ma->size - 1; 
   2.281 +	la->size = ma->size; 
   2.282  	la->my_class = ma->my_class;	
   2.283        }
   2.284  
   2.285 @@ -251,10 +415,17 @@
   2.286  	i->parent = la;
   2.287        }
   2.288  
   2.289 +      la->size--;
   2.290        la->my_class->erase(ma);
   2.291        m.set(a,0);
   2.292      }
   2.293  
   2.294 +    /**
   2.295 +     * \brief Removes the component of the given element from the structure.
   2.296 +     *
   2.297 +     * Removes the component of the given element from the structure.
   2.298 +     */
   2.299 +
   2.300      void eraseClass(const T &a) {
   2.301        IIter ma = m[a];
   2.302        if (ma == 0) return;
   2.303 @@ -301,16 +472,51 @@
   2.304        }
   2.305      };
   2.306  
   2.307 +    /**
   2.308 +     * \brief Sets the iterator to point to the first component.
   2.309 +     * 
   2.310 +     * Sets the iterator to point to the first component.
   2.311 +     *
   2.312 +     * With the \ref first, \ref valid and \ref next methods you can
   2.313 +     * iterate through the components. For example:
   2.314 +     * \code
   2.315 +     * UnionFindEnum<Graph::Node, Graph::NodeMap>::MapType map(G);
   2.316 +     * UnionFindEnum<Graph::Node, Graph::NodeMap> U(map);
   2.317 +     * UnionFindEnum<Graph::Node, Graph::NodeMap>::ClassIt iter;
   2.318 +     *  for (U.first(iter); U.valid(iter); U.next(iter)) {
   2.319 +     *    // iter is convertible to Graph::Node
   2.320 +     *    cout << iter << endl;
   2.321 +     *  }
   2.322 +     * \endcode
   2.323 +     */
   2.324  
   2.325      ClassIt& first(ClassIt& it) const {
   2.326        it.first(classes);
   2.327        return it;
   2.328      }
   2.329  
   2.330 +    /**
   2.331 +     * \brief Returns whether the iterator is valid.
   2.332 +     *
   2.333 +     * Returns whether the iterator is valid.
   2.334 +     *
   2.335 +     * With the \ref first, \ref valid and \ref next methods you can
   2.336 +     * iterate through the components. See the example here: \ref first.
   2.337 +     */
   2.338 +
   2.339      bool valid(ClassIt const &it) const {
   2.340        return it.valid(); 
   2.341      }
   2.342  
   2.343 +    /**
   2.344 +     * \brief Steps the iterator to the next component. 
   2.345 +     *
   2.346 +     * Steps the iterator to the next component.
   2.347 +     *
   2.348 +     * With the \ref first, \ref valid and \ref next methods you can
   2.349 +     * iterate through the components. See the example here: \ref first.
   2.350 +     */
   2.351 +
   2.352      ClassIt& next(ClassIt& it) const {
   2.353        it.next(classes);
   2.354        return it;
   2.355 @@ -351,23 +557,71 @@
   2.356      };
   2.357  
   2.358  
   2.359 +
   2.360 +    /**
   2.361 +     * \brief Sets the iterator to point to the first element of the component.
   2.362 +     * 
   2.363 +     * \anchor first2 
   2.364 +     * Sets the iterator to point to the first element of the component.
   2.365 +     *
   2.366 +     * With the \ref first2 "first", \ref valid2 "valid" 
   2.367 +     * and \ref next2 "next" methods you can
   2.368 +     * iterate through the elements of a component. For example
   2.369 +     * (iterating through the component of the node \e node):
   2.370 +     * \code
   2.371 +     * Graph::Node node = ...;
   2.372 +     * UnionFindEnum<Graph::Node, Graph::NodeMap>::MapType map(G);
   2.373 +     * UnionFindEnum<Graph::Node, Graph::NodeMap> U(map);
   2.374 +     * UnionFindEnum<Graph::Node, Graph::NodeMap>::ItemIt iiter;
   2.375 +     *   for (U.first(iiter, node); U.valid(iiter); U.next(iiter)) {
   2.376 +     *     // iiter is convertible to Graph::Node
   2.377 +     *     cout << iiter << endl;
   2.378 +     *   }
   2.379 +     * \endcode
   2.380 +     */
   2.381 +    
   2.382      ItemIt& first(ItemIt& it, const T& a) const {
   2.383        it.first( * _find(m[a])->my_class );
   2.384        return it;
   2.385      }
   2.386  
   2.387 +    /**
   2.388 +     * \brief Returns whether the iterator is valid.
   2.389 +     *
   2.390 +     * \anchor valid2
   2.391 +     * Returns whether the iterator is valid.
   2.392 +     *
   2.393 +     * With the \ref first2 "first", \ref valid2 "valid" 
   2.394 +     * and \ref next2 "next" methods you can
   2.395 +     * iterate through the elements of a component.
   2.396 +     * See the example here: \ref first2 "first".
   2.397 +     */
   2.398 +
   2.399      bool valid(ItemIt const &it) const {
   2.400        return it.valid(); 
   2.401      }
   2.402  
   2.403 +    /**
   2.404 +     * \brief Steps the iterator to the next component. 
   2.405 +     *
   2.406 +     * \anchor next2
   2.407 +     * Steps the iterator to the next component.
   2.408 +     *
   2.409 +     * With the \ref first2 "first", \ref valid2 "valid" 
   2.410 +     * and \ref next2 "next" methods you can
   2.411 +     * iterate through the elements of a component.
   2.412 +     * See the example here: \ref first2 "first".
   2.413 +     */
   2.414 +
   2.415      ItemIt& next(ItemIt& it) const {
   2.416        it.next();
   2.417        return it;
   2.418      }
   2.419      
   2.420 +  };
   2.421  
   2.422  
   2.423 -  };
   2.424 +  //! @}
   2.425  
   2.426  } //namespace hugo
   2.427  
     3.1 --- a/src/work/johanna/unionfind_test.cc	Wed Apr 28 16:25:34 2004 +0000
     3.2 +++ b/src/work/johanna/unionfind_test.cc	Wed Apr 28 20:55:18 2004 +0000
     3.3 @@ -75,11 +75,19 @@
     3.4    check(U.size(5) == 2);
     3.5    cout << "size of the class of 6: " << U.size(6) << endl;
     3.6    check(U.size(6) == 1);
     3.7 +  cout << "size of the class of 2: " << U.size(2) << endl;
     3.8 +  check(U.size(2) == 3);
     3.9  
    3.10    cout <<"erase 1: " << endl;
    3.11    U.erase(1);
    3.12    print(U);
    3.13  
    3.14 +  cout << "size of the class of 4: " << U.size(4) << endl;
    3.15 +  check(U.size(4) == 2);
    3.16 +  cout << "size of the class of 2: " << U.size(2) << endl;
    3.17 +  check(U.size(2) == 2);
    3.18 +
    3.19 +
    3.20    cout <<"erase 1: " << endl;
    3.21    U.erase(1);
    3.22    print(U);
    3.23 @@ -92,11 +100,46 @@
    3.24    U.split(5);
    3.25    print(U);
    3.26  
    3.27 +
    3.28 +  cout << "size of the class of 4: " << U.size(4) << endl;
    3.29 +  check(U.size(4) == 2);
    3.30 +  cout << "size of the class of 3: " << U.size(3) << endl;
    3.31 +  check(U.size(3) == 1);
    3.32 +  cout << "size of the class of 2: " << U.size(2) << endl;
    3.33 +  check(U.size(2) == 2);
    3.34 +
    3.35 +
    3.36    cout << "Joining 3 - 4 and 2 - 4 ..." << endl;
    3.37    check(U.join(3,4));
    3.38    check(!U.join(2,4));
    3.39    print(U);
    3.40  
    3.41 +
    3.42 +  cout << "size of the class of 4: " << U.size(4) << endl;
    3.43 +  check(U.size(4) == 3);
    3.44 +  cout << "size of the class of 3: " << U.size(3) << endl;
    3.45 +  check(U.size(3) == 3);
    3.46 +  cout << "size of the class of 2: " << U.size(2) << endl;
    3.47 +  check(U.size(2) == 3);
    3.48 +
    3.49 +  cout << "makeRep(4)" << endl;
    3.50 +  U.makeRep(4);
    3.51 +  print(U);
    3.52 +  cout << "makeRep(3)" << endl;
    3.53 +  U.makeRep(3);
    3.54 +  print(U);
    3.55 +  cout << "makeRep(2)" << endl;
    3.56 +  U.makeRep(2);
    3.57 +  print(U);
    3.58 +
    3.59 +  cout << "size of the class of 4: " << U.size(4) << endl;
    3.60 +  check(U.size(4) == 3);
    3.61 +  cout << "size of the class of 3: " << U.size(3) << endl;
    3.62 +  check(U.size(3) == 3);
    3.63 +  cout << "size of the class of 2: " << U.size(2) << endl;
    3.64 +  check(U.size(2) == 3);
    3.65 +
    3.66 +
    3.67    cout << "eraseClass 4 ..." << endl;
    3.68    U.eraseClass(4);
    3.69    print(U);