[Lemon-commits] [lemon_svn] beckerjc: r613 - in hugo/trunk: doc src/work/johanna
Lemon SVN
svn at lemon.cs.elte.hu
Mon Nov 6 20:40:34 CET 2006
Author: beckerjc
Date: Wed Apr 28 22:55:18 2004
New Revision: 613
Modified:
hugo/trunk/doc/Doxyfile
hugo/trunk/src/work/johanna/unionfind.h
hugo/trunk/src/work/johanna/unionfind_test.cc
Log:
Doc for the union-find structures.
Modified: hugo/trunk/doc/Doxyfile
==============================================================================
--- hugo/trunk/doc/Doxyfile (original)
+++ hugo/trunk/doc/Doxyfile Wed Apr 28 22:55:18 2004
@@ -405,6 +405,7 @@
../src/work/alpar/list_graph.h \
../src/work/athos/minlengthpaths.h \
../src/work/klao/path.h \
+ ../src/work/johanna/unionfind.h \
../src/work/marci/graph_wrapper.h
Modified: hugo/trunk/src/work/johanna/unionfind.h
==============================================================================
--- hugo/trunk/src/work/johanna/unionfind.h (original)
+++ hugo/trunk/src/work/johanna/unionfind.h Wed Apr 28 22:55:18 2004
@@ -2,6 +2,11 @@
#ifndef HUGO_UNION_FIND_H
#define HUGO_UNION_FIND_H
+//!ingroup auxdat
+//!\file
+//!\brief Union-Find data structures.
+
+
#include <vector>
#include <list>
#include <utility>
@@ -11,6 +16,24 @@
namespace hugo {
+ //! \addtogroup auxdat
+ //! @{
+
+ /**
+ * \brief A \e Union-Find data structure implementation
+ *
+ * The class implements the \e Union-Find data structure.
+ * The union operation uses rank heuristic, while
+ * the find operation uses path compresson.
+ * This is a very simple but efficient implementation, providing
+ * only four methods: join (union), find, insert and size.
+ * For more features see the \ref UnionFindEnum class.
+ *
+ * \pre The elements are automatically added only if the map
+ * given to the constructor was filled with -1's. Otherwise you
+ * need to add all the elements by the \ref insert() method.
+ */
+
template <typename T, typename TIntMap>
class UnionFind {
@@ -25,6 +48,12 @@
public:
UnionFind(TIntMap& m) : map(m) {}
+ /**
+ * \brief Returns the index of the element's component.
+ *
+ * The method returns the index of the element's component.
+ * This is an integer between zero and the number of inserted elements.
+ */
int find(T a)
{
@@ -45,6 +74,19 @@
return comp;
}
+ /**
+ * \brief Insert a new element into the structure.
+ *
+ * This method inserts a new element into the data structure.
+ *
+ * It is not required to use this method:
+ * if the map given to the constructor was filled
+ * with -1's then it is called automatically
+ * on the first \ref find or \ref join.
+ *
+ * The method returns the index of the new component.
+ */
+
int insert(T a)
{
int n = data.size();
@@ -53,6 +95,15 @@
return n;
}
+ /**
+ * \brief Joining the components of element \e a and element \e b.
+ *
+ * This is the \e union operation of the Union-Find structure.
+ * Joins the component of elemenent \e a and component of
+ * element \e b. If \e a and \e b are in the same component then
+ * it returns false otherwise it returns true.
+ */
+
bool join(T a, T b)
{
int ca = find(a);
@@ -72,6 +123,12 @@
return true;
}
+ /**
+ * \brief Returns the size of the component of element \e a.
+ *
+ * Returns the size of the component of element \e a.
+ */
+
int size(T a)
{
int ca = find(a);
@@ -86,6 +143,27 @@
/*******************************************************/
+#ifdef DEVELOPMENT_DOCS
+
+ /**
+ * \brief The auxiliary class for the \ref UnionFindEnum class.
+ *
+ * In the \ref UnionFindEnum class all components are represented as
+ * a std::list.
+ * Items of these lists are UnionFindEnumItem structures.
+ *
+ * The class has four fields:
+ * - T me - the actual element
+ * - IIter parent - the parent of the element in the union-find structure
+ * - int size - the size of the component of the element.
+ * Only valid if the element
+ * is the leader of the component.
+ * - CIter my_class - pointer into the list of components
+ * pointing to the component of the element.
+ * Only valid if the element is the leader of the component.
+ */
+
+#endif
template <typename T>
struct UnionFindEnumItem {
@@ -105,6 +183,24 @@
me(_me), size(1), my_class(_my_class) {}
};
+
+ /**
+ * \brief A \e Union-Find data structure implementation which
+ * is able to enumerate the components.
+ *
+ * The class implements an \e Union-Find data structure
+ * which is able to enumerate the components and the items in
+ * a component. If you don't need this feature then perhaps it's
+ * better to use the \ref UnionFind class which is more efficient.
+ *
+ * The union operation uses rank heuristic, while
+ * the find operation uses path compresson.
+ *
+ * \pre You
+ * need to add all the elements by the \ref insert() method.
+ */
+
+
template <typename T, template <typename Item> class Map>
class UnionFindEnum {
@@ -124,10 +220,6 @@
MapType& m;
ClassList classes;
- // IIter where(const T &a) { return m[a]; }
- // IIter parent(IIter a) { return a->parent; }
- // P sibling(P a) { return &m[a->sibling]; }
-
IIter _find(IIter a) const {
IIter comp = a;
IIter next;
@@ -146,6 +238,14 @@
public:
UnionFindEnum(MapType& _m) : m(_m) {}
+
+ /**
+ * \brief Insert the given element into a new component.
+ *
+ * This method creates a new component consisting only of the
+ * given element.
+ */
+
void insert(const T &a)
{
@@ -163,10 +263,26 @@
}
+ /**
+ * \brief Find the leader of the component of the given element.
+ *
+ * The method returns the leader of the component of the given element.
+ */
+
T find(const T &a) const {
return _find(m[a])->me;
}
+
+ /**
+ * \brief Joining the component of element \e a and element \e b.
+ *
+ * This is the \e union operation of the Union-Find structure.
+ * Joins the component of elemenent \e a and component of
+ * element \e b. If \e a and \e b are in the same component then
+ * returns false else returns true.
+ */
+
bool join(T a, T b) {
IIter ca = _find(m[a]);
@@ -202,11 +318,25 @@
return true;
}
+
+ /**
+ * \brief Returns the size of the component of element \e a.
+ *
+ * Returns the size of the component of element \e a.
+ */
+
int size(const T &a) const {
return _find(m[a])->size;
}
-
+
+ /**
+ * \brief Split up the component of the element.
+ *
+ * Splitting the component of the element into sigleton
+ * components (component of size one).
+ */
+
void split(const T &a) {
IIter ca = _find(m[a]);
@@ -230,6 +360,40 @@
return;
}
+
+ /**
+ * \brief Set the given element to the leader element of its component.
+ *
+ * Set the given element to the leader element of its component.
+ */
+
+ void makeRep(const T &a) {
+
+ IIter ia = m[a];
+ IIter la = _find(ia);
+ if (la == ia) return;
+
+ ia->my_class = la->my_class;
+ la->my_class = 0;
+
+ ia->size = la->size;
+
+ CIter l = ia->my_class;
+ l->splice(l->begin(),*l,ia);
+
+ ia->parent = ia;
+ la->parent = ia;
+ }
+
+
+ /**
+ * \brief Remove the given element from the structure.
+ *
+ * Remove the given element from the structure.
+ *
+ * Removes the element from its component and if the component becomes
+ * empty then removes that component from the component list.
+ */
void erase(const T &a) {
IIter ma = m[a];
@@ -243,7 +407,7 @@
return;
}
++la;
- la->size = ma->size - 1;
+ la->size = ma->size;
la->my_class = ma->my_class;
}
@@ -251,10 +415,17 @@
i->parent = la;
}
+ la->size--;
la->my_class->erase(ma);
m.set(a,0);
}
+ /**
+ * \brief Removes the component of the given element from the structure.
+ *
+ * Removes the component of the given element from the structure.
+ */
+
void eraseClass(const T &a) {
IIter ma = m[a];
if (ma == 0) return;
@@ -301,16 +472,51 @@
}
};
+ /**
+ * \brief Sets the iterator to point to the first component.
+ *
+ * Sets the iterator to point to the first component.
+ *
+ * With the \ref first, \ref valid and \ref next methods you can
+ * iterate through the components. For example:
+ * \code
+ * UnionFindEnum<Graph::Node, Graph::NodeMap>::MapType map(G);
+ * UnionFindEnum<Graph::Node, Graph::NodeMap> U(map);
+ * UnionFindEnum<Graph::Node, Graph::NodeMap>::ClassIt iter;
+ * for (U.first(iter); U.valid(iter); U.next(iter)) {
+ * // iter is convertible to Graph::Node
+ * cout << iter << endl;
+ * }
+ * \endcode
+ */
ClassIt& first(ClassIt& it) const {
it.first(classes);
return it;
}
+ /**
+ * \brief Returns whether the iterator is valid.
+ *
+ * Returns whether the iterator is valid.
+ *
+ * With the \ref first, \ref valid and \ref next methods you can
+ * iterate through the components. See the example here: \ref first.
+ */
+
bool valid(ClassIt const &it) const {
return it.valid();
}
+ /**
+ * \brief Steps the iterator to the next component.
+ *
+ * Steps the iterator to the next component.
+ *
+ * With the \ref first, \ref valid and \ref next methods you can
+ * iterate through the components. See the example here: \ref first.
+ */
+
ClassIt& next(ClassIt& it) const {
it.next(classes);
return it;
@@ -351,23 +557,71 @@
};
+
+ /**
+ * \brief Sets the iterator to point to the first element of the component.
+ *
+ * \anchor first2
+ * Sets the iterator to point to the first element of the component.
+ *
+ * With the \ref first2 "first", \ref valid2 "valid"
+ * and \ref next2 "next" methods you can
+ * iterate through the elements of a component. For example
+ * (iterating through the component of the node \e node):
+ * \code
+ * Graph::Node node = ...;
+ * UnionFindEnum<Graph::Node, Graph::NodeMap>::MapType map(G);
+ * UnionFindEnum<Graph::Node, Graph::NodeMap> U(map);
+ * UnionFindEnum<Graph::Node, Graph::NodeMap>::ItemIt iiter;
+ * for (U.first(iiter, node); U.valid(iiter); U.next(iiter)) {
+ * // iiter is convertible to Graph::Node
+ * cout << iiter << endl;
+ * }
+ * \endcode
+ */
+
ItemIt& first(ItemIt& it, const T& a) const {
it.first( * _find(m[a])->my_class );
return it;
}
+ /**
+ * \brief Returns whether the iterator is valid.
+ *
+ * \anchor valid2
+ * Returns whether the iterator is valid.
+ *
+ * With the \ref first2 "first", \ref valid2 "valid"
+ * and \ref next2 "next" methods you can
+ * iterate through the elements of a component.
+ * See the example here: \ref first2 "first".
+ */
+
bool valid(ItemIt const &it) const {
return it.valid();
}
+ /**
+ * \brief Steps the iterator to the next component.
+ *
+ * \anchor next2
+ * Steps the iterator to the next component.
+ *
+ * With the \ref first2 "first", \ref valid2 "valid"
+ * and \ref next2 "next" methods you can
+ * iterate through the elements of a component.
+ * See the example here: \ref first2 "first".
+ */
+
ItemIt& next(ItemIt& it) const {
it.next();
return it;
}
+ };
- };
+ //! @}
} //namespace hugo
Modified: hugo/trunk/src/work/johanna/unionfind_test.cc
==============================================================================
--- hugo/trunk/src/work/johanna/unionfind_test.cc (original)
+++ hugo/trunk/src/work/johanna/unionfind_test.cc Wed Apr 28 22:55:18 2004
@@ -75,11 +75,19 @@
check(U.size(5) == 2);
cout << "size of the class of 6: " << U.size(6) << endl;
check(U.size(6) == 1);
+ cout << "size of the class of 2: " << U.size(2) << endl;
+ check(U.size(2) == 3);
cout <<"erase 1: " << endl;
U.erase(1);
print(U);
+ cout << "size of the class of 4: " << U.size(4) << endl;
+ check(U.size(4) == 2);
+ cout << "size of the class of 2: " << U.size(2) << endl;
+ check(U.size(2) == 2);
+
+
cout <<"erase 1: " << endl;
U.erase(1);
print(U);
@@ -92,11 +100,46 @@
U.split(5);
print(U);
+
+ cout << "size of the class of 4: " << U.size(4) << endl;
+ check(U.size(4) == 2);
+ cout << "size of the class of 3: " << U.size(3) << endl;
+ check(U.size(3) == 1);
+ cout << "size of the class of 2: " << U.size(2) << endl;
+ check(U.size(2) == 2);
+
+
cout << "Joining 3 - 4 and 2 - 4 ..." << endl;
check(U.join(3,4));
check(!U.join(2,4));
print(U);
+
+ cout << "size of the class of 4: " << U.size(4) << endl;
+ check(U.size(4) == 3);
+ cout << "size of the class of 3: " << U.size(3) << endl;
+ check(U.size(3) == 3);
+ cout << "size of the class of 2: " << U.size(2) << endl;
+ check(U.size(2) == 3);
+
+ cout << "makeRep(4)" << endl;
+ U.makeRep(4);
+ print(U);
+ cout << "makeRep(3)" << endl;
+ U.makeRep(3);
+ print(U);
+ cout << "makeRep(2)" << endl;
+ U.makeRep(2);
+ print(U);
+
+ cout << "size of the class of 4: " << U.size(4) << endl;
+ check(U.size(4) == 3);
+ cout << "size of the class of 3: " << U.size(3) << endl;
+ check(U.size(3) == 3);
+ cout << "size of the class of 2: " << U.size(2) << endl;
+ check(U.size(2) == 3);
+
+
cout << "eraseClass 4 ..." << endl;
U.eraseClass(4);
print(U);
More information about the Lemon-commits
mailing list