[Lemon-commits] [lemon_svn] deba: r2930 - in hugo/trunk: lemon test
Lemon SVN
svn at lemon.cs.elte.hu
Mon Nov 6 21:51:18 CET 2006
Author: deba
Date: Wed Sep 6 13:17:12 2006
New Revision: 2930
Modified:
hugo/trunk/lemon/kruskal.h
hugo/trunk/lemon/max_matching.h
hugo/trunk/lemon/unionfind.h
hugo/trunk/test/unionfind_test.cc
Log:
UnionFind
Changing the representation of the union-find
it has the same running time but it takes just 2/3 space
! does not auto insert items /performance/
UnionFindEnum
Changing the interface - more convenient to UnionFind
Does not based on the stl data structures /it could be disadvantage/
=> does not use singular iterator assignment /not stl conform, but always work/
Just new iterator interface
MaxMatching + UnionFindTest
Using new iterator interface instead of the old
Modified: hugo/trunk/lemon/kruskal.h
==============================================================================
--- hugo/trunk/lemon/kruskal.h (original)
+++ hugo/trunk/lemon/kruskal.h Wed Sep 6 13:17:12 2006
@@ -24,6 +24,8 @@
#include <lemon/unionfind.h>
#include <lemon/bits/utility.h>
#include <lemon/bits/traits.h>
+#include <lemon/time_measure.h>
+#include <iostream>
///\ingroup spantree
///\file
@@ -117,8 +119,12 @@
typedef typename GR::template NodeMap<int> NodeIntMap;
typedef typename GR::Node Node;
- NodeIntMap comp(g, -1);
- UnionFind<Node,NodeIntMap> uf(comp);
+ Timer timer;
+ NodeIntMap comp(g);
+ UnionFind<Node,NodeIntMap> uf(comp);
+ for (typename GR::NodeIt it(g); it != INVALID; ++it) {
+ uf.insert(it);
+ }
EdgeCost tot_cost = 0;
for (typename IN::const_iterator p = in.begin();
@@ -132,6 +138,7 @@
out.set((*p).first, false);
}
}
+ std::cout << timer << std::endl;
return tot_cost;
}
Modified: hugo/trunk/lemon/max_matching.h
==============================================================================
--- hugo/trunk/lemon/max_matching.h (original)
+++ hugo/trunk/lemon/max_matching.h Wed Sep 6 13:17:12 2006
@@ -65,7 +65,8 @@
typedef typename Graph::NodeIt NodeIt;
typedef typename Graph::IncEdgeIt IncEdgeIt;
- typedef UnionFindEnum<Node, Graph::template NodeMap> UFE;
+ typedef typename Graph::template NodeMap<int> UFECrossRef;
+ typedef UnionFindEnum<Node, UFECrossRef> UFE;
public:
@@ -121,10 +122,12 @@
//undefined for the base nodes of the blossoms (i.e. for the
//representative elements of UFE blossom) and for the nodes in C
- typename UFE::MapType blossom_base(g);
+ UFECrossRef blossom_base(g);
UFE blossom(blossom_base);
- typename UFE::MapType tree_base(g);
+
+ UFECrossRef tree_base(g);
UFE tree(tree_base);
+
//If these UFE's would be members of the class then also
//blossom_base and tree_base should be a member.
@@ -549,15 +552,13 @@
_mate.set(u,tmp);
}
Node y=blossom.find(x);
- typename UFE::ItemIt it;
- for (tree.first(it,blossom.find(x)); tree.valid(it); tree.next(it)) {
- if ( position[it] == D ) {
- typename UFE::ItemIt b_it;
- for (blossom.first(b_it,it); blossom.valid(b_it); blossom.next(b_it)) {
- position.set( b_it ,C);
+ for (typename UFE::ItemIt tit(tree, y); tit != INVALID; ++tit) {
+ if ( position[tit] == D ) {
+ for (typename UFE::ItemIt bit(blossom, tit); bit != INVALID; ++bit) {
+ position.set( bit ,C);
}
- blossom.eraseClass(it);
- } else position.set( it ,C);
+ blossom.eraseClass(tit);
+ } else position.set( tit ,C);
}
tree.eraseClass(y);
Modified: hugo/trunk/lemon/unionfind.h
==============================================================================
--- hugo/trunk/lemon/unionfind.h (original)
+++ hugo/trunk/lemon/unionfind.h Wed Sep 6 13:17:12 2006
@@ -36,701 +36,543 @@
//! \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 compression.
- * 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.
- *
- * It is primarily used in Kruskal algorithm for finding minimal
- * cost spanning tree in a graph.
- * \sa kruskal()
- *
- * \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.
- * \bug It is not clear what the constructor parameter is used for.
- */
-
- template <typename T, typename TIntMap>
+ /// \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 compression.
+ /// 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.
+ ///
+ /// It is primarily used in Kruskal algorithm for finding minimal
+ /// cost spanning tree in a graph.
+ /// \sa kruskal()
+ ///
+ /// \pre You need to add all the elements by the \ref insert()
+ /// method.
+ template <typename Item, typename ItemIntMap>
class UnionFind {
public:
- typedef T ElementType;
- typedef std::pair<int,int> PairType;
+ typedef Item ElementType;
private:
- std::vector<PairType> data;
- TIntMap& map;
+ // If the items vector stores negative value for an item then
+ // that item is root item and it has -items[it] component size.
+ // Else the items[it] contains the index of the parent.
+ std::vector<int> items;
+ ItemIntMap& index;
+
+ bool rep(int idx) const {
+ return items[idx] < 0;
+ }
+
+ int repIndex(int idx) const {
+ int k = idx;
+ while (!rep(k)) {
+ k = items[k] ;
+ }
+ while (idx != k) {
+ int next = items[idx];
+ const_cast<int&>(items[idx]) = k;
+ idx = next;
+ }
+ return k;
+ }
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)
- {
- int comp0 = map[a];
- if (comp0 < 0) {
- return insert(a);
- }
- int comp = comp0;
- int next;
- while ( (next = data[comp].first) != comp) {
- comp = next;
- }
- while ( (next = data[comp0].first) != comp) {
- data[comp0].first = comp;
- comp0 = next;
- }
-
- return comp;
- }
-
- /**
- * \brief Inserts 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();
- data.push_back(std::make_pair(n, 1));
- map.set(a,n);
+ /// \brief Constructor
+ ///
+ /// Constructor of the UnionFind class. You should give an item to
+ /// integer map which will be used from the data structure. If you
+ /// modify directly this map that may cause segmentation fault,
+ /// invalid data structure, or infinite loop when you use again
+ /// the union-find.
+ UnionFind(ItemIntMap& m) : index(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(const Item& a) {
+ return repIndex(index[a]);
+ }
+
+ /// \brief Inserts a new element into the structure.
+ ///
+ /// This method inserts a new element into the data structure.
+ ///
+ /// The method returns the index of the new component.
+ int insert(const Item& a) {
+ int n = items.size();
+ items.push_back(-1);
+ index.set(a,n);
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 element \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);
- int cb = find(b);
+ /// \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 element \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(const Item& a, const Item& b) {
+ int ka = repIndex(index[a]);
+ int kb = repIndex(index[b]);
- if ( ca == cb )
+ if ( ka == kb )
return false;
- if ( data[ca].second > data[cb].second ) {
- data[cb].first = ca;
- data[ca].second += data[cb].second;
- }
- else {
- data[ca].first = cb;
- data[cb].second += data[ca].second;
+ if (items[ka] < items[kb]) {
+ items[ka] += items[kb];
+ items[kb] = ka;
+ } else {
+ items[kb] += items[ka];
+ items[ka] = kb;
}
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);
- return data[ca].second;
+ /// \brief Returns the size of the component of element \e a.
+ ///
+ /// Returns the size of the component of element \e a.
+ int size(const Item& a) {
+ int k = repIndex(index[a]);
+ return - items[k];
}
};
-
-
- /*******************************************************/
-
-
-#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 {
-
- typedef std::list<UnionFindEnumItem> ItemList;
- typedef std::list<ItemList> ClassList;
- typedef typename ItemList::iterator IIter;
- typedef typename ClassList::iterator CIter;
-
- T me;
- IIter parent;
- int size;
- CIter my_class;
-
- UnionFindEnumItem() {}
- UnionFindEnumItem(const T &_me, CIter _my_class):
- 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 a \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 compression.
- *
- * \pre You
- * need to add all the elements by the \ref insert() method.
- */
-
-
- template <typename T, template <typename Item> class Map>
+ /// \brief A \e Union-Find data structure implementation which
+ /// is able to enumerate the components.
+ ///
+ /// The class implements a \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 compression.
+ ///
+ /// \pre You need to add all the elements by the \ref insert()
+ /// method.
+ ///
+ template <typename _Item, typename _ItemIntMap>
class UnionFindEnum {
-
- typedef std::list<UnionFindEnumItem<T> > ItemList;
- typedef std::list<ItemList> ClassList;
- typedef typename ItemList::iterator IIter;
- typedef typename ItemList::const_iterator IcIter;
- typedef typename ClassList::iterator CIter;
- typedef typename ClassList::const_iterator CcIter;
-
public:
- typedef T ElementType;
- typedef UnionFindEnumItem<T> ItemType;
- typedef Map< IIter > MapType;
-
+
+ typedef _Item Item;
+ typedef _ItemIntMap ItemIntMap;
+
private:
- MapType& m;
- ClassList classes;
-
- IIter _find(IIter a) const {
- IIter comp = a;
- IIter next;
- while( (next = comp->parent) != comp ) {
- comp = next;
- }
-
- IIter comp1 = a;
- while( (next = comp1->parent) != comp ) {
- comp1->parent = comp->parent;
- comp1 = next;
- }
- return comp;
- }
-
- const ItemList& classOf(const T &a) const {
- return *_find(m[a])->my_class;
- }
-
- public:
- UnionFindEnum(MapType& _m) : m(_m) {}
-
-
- /**
- * \brief Inserts the given element into a new component.
- *
- * This method creates a new component consisting only of the
- * given element.
- */
-
- void insert(const T &a)
- {
-
-
- classes.push_back(ItemList());
- CIter aclass = classes.end();
- --aclass;
+
+ // If the parent stores negative value for an item then that item
+ // is root item and it has -items[it].parent component size. Else
+ // the items[it].parent contains the index of the parent.
+ //
+ // The \c nextItem and \c prevItem provides the double-linked
+ // cyclic list of one component's items. The \c prevClass and
+ // \c nextClass gives the double linked list of the representant
+ // items.
+ struct ItemT {
+ int parent;
+ Item item;
- ItemList &alist = *aclass;
- alist.push_back(ItemType(a, aclass));
- IIter ai = alist.begin();
+ int nextItem, prevItem;
+ int nextClass, prevClass;
+ };
- ai->parent = ai;
- m.set(a, ai);
+ std::vector<ItemT> items;
+ ItemIntMap& index;
- }
+ int firstClass;
- /**
- * \brief Inserts the given element into the component of the others.
- *
- * This methods inserts the element \e a into the component of the
- * element \e comp.
- */
- void insert(const T &a, const T &comp) {
-
- IIter clit = _find(m[comp]);
- ItemList &c = *clit->my_class;
- c.push_back(ItemType(a,CIter()));
- IIter ai = c.end();
- --ai;
- ai->parent = clit;
- m.set(a, ai);
- ++clit->size;
+ bool rep(int idx) const {
+ return items[idx].parent < 0;
}
-
- /**
- * \brief Finds 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 element \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]);
- IIter cb = _find(m[b]);
-
- if ( ca == cb ) {
- return false;
+ int repIndex(int idx) const {
+ int k = idx;
+ while (!rep(k)) {
+ k = items[k].parent;
}
-
- if ( ca->size > cb->size ) {
-
- cb->parent = ca->parent;
- ca->size += cb->size;
-
- ItemList &alist = *ca->my_class;
- alist.splice(alist.end(),*cb->my_class);
-
- classes.erase(cb->my_class);
+ while (idx != k) {
+ int next = items[idx].parent;
+ const_cast<int&>(items[idx].parent) = k;
+ idx = next;
}
- else {
-
- ca->parent = cb->parent;
- cb->size += ca->size;
-
- ItemList &blist = *cb->my_class;
- blist.splice(blist.end(),*ca->my_class);
-
- classes.erase(ca->my_class);
- }
-
- return true;
+ return k;
}
+ void unlaceClass(int k) {
+ if (items[k].prevClass != -1) {
+ items[items[k].prevClass].nextClass = items[k].nextClass;
+ } else {
+ firstClass = items[k].nextClass;
+ }
+ if (items[k].nextClass != -1) {
+ items[items[k].nextClass].prevClass = items[k].prevClass;
+ }
+ }
- /**
- * \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;
+ void spliceItems(int ak, int bk) {
+ items[items[ak].prevItem].nextItem = bk;
+ items[items[bk].prevItem].nextItem = ak;
+ int tmp = items[ak].prevItem;
+ items[ak].prevItem = items[bk].prevItem;
+ items[bk].prevItem = tmp;
+
}
+ public:
- /**
- * \brief Splits 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]);
-
- if ( ca->size == 1 )
- return;
+ UnionFindEnum(ItemIntMap& _index)
+ : items(), index(_index), firstClass(-1) {}
+
+ /// \brief Inserts the given element into a new component.
+ ///
+ /// This method creates a new component consisting only of the
+ /// given element.
+ ///
+ void insert(const Item& item) {
+ ItemT t;
+
+ int idx = items.size();
+ index.set(item, idx);
+
+ t.nextItem = idx;
+ t.prevItem = idx;
+ t.item = item;
+ t.parent = -1;
- CIter aclass = ca->my_class;
-
- for(IIter curr = ca; ++curr != aclass->end(); curr=ca) {
- classes.push_back(ItemList());
- CIter nl = --classes.end();
- nl->splice(nl->end(), *aclass, curr);
-
- curr->size=1;
- curr->parent=curr;
- curr->my_class = nl;
+ t.nextClass = firstClass;
+ if (firstClass != -1) {
+ items[firstClass].prevClass = idx;
}
+ t.prevClass = -1;
+ firstClass = idx;
- ca->size=1;
- return;
+ items.push_back(t);
}
+ /// \brief Inserts the given element into the component of the others.
+ ///
+ /// This methods inserts the element \e a into the component of the
+ /// element \e comp.
+ void insert(const Item& item, const Item& comp) {
+ int k = repIndex(index[comp]);
+ ItemT t;
- /**
- * \brief Sets the given element to the leader element of its component.
- *
- * Sets the given element to the leader element of its component.
- */
-
- void makeRep(const T &a) {
+ int idx = items.size();
+ index.set(item, idx);
- IIter ia = m[a];
- IIter la = _find(ia);
- if (la == ia) return;
+ t.prevItem = k;
+ t.nextItem = items[k].nextItem;
+ items[items[k].nextItem].prevItem = idx;
+ items[k].nextItem = idx;
- ia->my_class = la->my_class;
+ t.item = item;
+ t.parent = k;
- ia->size = la->size;
+ --items[k].parent;
- CIter l = ia->my_class;
- l->splice(l->begin(),*l,ia);
-
- ia->parent = ia;
- la->parent = ia;
+ items.push_back(t);
}
- /**
- * \brief Moves the given element to another component.
- *
- * This method moves the element \e a from its component
- * to the component of \e comp.
- * If \e a and \e comp are in the same component then
- * it returns false otherwise it returns true.
- */
+ /// \brief Finds the leader of the component of the given element.
+ ///
+ /// The method returns the leader of the component of the given element.
+ const Item& find(const Item &item) const {
+ return items[repIndex(index[item])].item;
+ }
- bool move(const T &a, const T &comp) {
+ /// \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 element \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(const Item& a, const Item& b) {
- IIter ai = m[a];
- IIter lai = _find(ai);
- IIter clit = _find(m[comp]);
+ int ak = repIndex(index[a]);
+ int bk = repIndex(index[b]);
- if (lai == clit)
+ if (ak == bk) {
return false;
-
- ItemList &cl = *clit->my_class,
- &al = *lai->my_class;
-
- bool is_leader = (lai == ai);
- bool singleton = false;
-
- if (is_leader) {
- ++lai;
}
- cl.splice(cl.end(), al, ai);
-
- if (is_leader) {
- if (ai->size == 1) {
- classes.erase(ai->my_class);
- singleton = true;
- }
- else {
- lai->size = ai->size;
- lai->my_class = ai->my_class;
- }
+ if ( items[ak].parent < items[bk].parent ) {
+ unlaceClass(bk);
+ items[ak].parent += items[bk].parent;
+ items[bk].parent = ak;
+ } else {
+ unlaceClass(bk);
+ items[bk].parent += items[ak].parent;
+ items[ak].parent = bk;
}
- if (!singleton) {
- for (IIter i = lai; i != al.end(); ++i)
- i->parent = lai;
- --lai->size;
- }
-
- ai->parent = clit;
- ++clit->size;
+ spliceItems(ak, bk);
return true;
}
-
- /**
- * \brief Removes 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.
- *
- * It is an error to remove an element which is not in the structure.
- */
- void erase(const T &a) {
-
- IIter ma = m[a];
-
- IIter la = _find(ma);
- if (la == ma) {
- if (ma -> size == 1){
- classes.erase(ma->my_class);
- return;
- }
- ++la;
- la->size = ma->size;
- la->my_class = ma->my_class;
- }
-
- for (IIter i = la; i != la->my_class->end(); ++i) {
- i->parent = la;
- }
-
- la->size--;
- la->my_class->erase(ma);
- }
-
- /**
- * \brief Removes the component of the given element from the structure.
- *
- * Removes the component of the given element from the structure.
- *
- * It is an error to give an element which is not in the structure.
- */
-
- void eraseClass(const T &a) {
- IIter ma = m[a];
- classes.erase(_find(ma)->my_class);
+ /// \brief Returns the size of the component of element \e a.
+ ///
+ /// Returns the size of the component of element \e a.
+ int size(const Item &item) const {
+ return - items[repIndex(index[item])].parent;
+ }
+
+ /// \brief Splits up the component of the element.
+ ///
+ /// Splitting the component of the element into sigleton
+ /// components (component of size one).
+ void split(const Item &item) {
+ int k = repIndex(index[item]);
+ int idx = items[k].nextItem;
+ while (idx != k) {
+ int next = items[idx].nextItem;
+
+ items[idx].parent = -1;
+ items[idx].prevItem = idx;
+ items[idx].nextItem = idx;
+
+ items[idx].nextClass = firstClass;
+ items[firstClass].prevClass = idx;
+ firstClass = idx;
+
+ idx = next;
+ }
+
+ items[idx].parent = -1;
+ items[idx].prevItem = idx;
+ items[idx].nextItem = idx;
+
+ items[firstClass].prevClass = -1;
}
-
- class ClassIt {
- friend class UnionFindEnum;
-
- CcIter i;
- const ClassList *l;
-
- public:
- ClassIt(Invalid): l(0) {}
- ClassIt() {}
- ClassIt(UnionFindEnum const &ufe) {
- l = &ufe.classes;
- i = l->begin();
- }
+ /// \brief Sets the given element to the leader element of its component.
+ ///
+ /// Sets the given element to the leader element of its component.
+ void makeRep(const Item &item) {
+ int nk = index[item];
+ int k = repIndex(nk);
+ if (nk == k) return;
- operator const T& () const {
- ItemList const &ll = *i;
- return (ll.begin())->me;
- }
- bool operator == (ClassIt const &it) const {
- return (l==it.l && i==it.i) || (!valid() && !it.valid());
- }
- bool operator != (ClassIt const &it) const {
- return !(*this == it);
+ if (items[k].prevClass != -1) {
+ items[items[k].prevClass].nextClass = nk;
+ } else {
+ firstClass = nk;
}
- bool operator < (ClassIt const &it) const {
- return (i < it.i);
+ if (items[k].nextClass != -1) {
+ items[items[k].nextClass].prevClass = nk;
}
-
- bool operator==(Invalid) const {
- return !valid();
- }
- bool operator!=(Invalid) const {
- return valid();
- }
-
- ClassIt& operator++() {
- ++i;
- return *this;
+
+ int idx = items[k].nextItem;
+ while (idx != k) {
+ items[idx].parent = nk;
+ idx = items[idx].nextItem;
}
+
+ items[nk].parent = items[k].parent;
+ items[k].parent = nk;
+ }
- // obsoleted:
- bool valid() const { return l!=0 && i!=l->end(); }
- };
-
- /**
- * \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
- *
- * \bug obsoleted, use the new LEMON iterator interface instead
- */
-
- ClassIt& first(ClassIt& it) const {
- it = ClassIt(*this);
- 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.
- *
- * \bug obsoleted, use the new LEMON iterator interface instead
- */
-
- 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 {
- return ++it;
+ /// \brief Removes 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.
+ ///
+ /// \warning It is an error to remove an element which is not in
+ /// the structure.
+ void erase(const Item &item) {
+ int idx = index[item];
+ if (rep(idx)) {
+ int k = idx;
+ if (items[k].parent == -1) {
+ unlaceClass(idx);
+ return;
+ } else {
+ int nk = items[k].nextItem;
+ if (items[k].prevClass != -1) {
+ items[items[k].prevClass].nextClass = nk;
+ } else {
+ firstClass = nk;
+ }
+ if (items[k].nextClass != -1) {
+ items[items[k].nextClass].prevClass = nk;
+ }
+
+ int idx = items[k].nextItem;
+ while (idx != k) {
+ items[idx].parent = nk;
+ idx = items[idx].nextItem;
+ }
+
+ items[nk].parent = items[k].parent + 1;
+ }
+ } else {
+
+ int k = repIndex(idx);
+ idx = items[k].nextItem;
+ while (idx != k) {
+ items[idx].parent = k;
+ idx = items[idx].nextItem;
+ }
+
+ ++items[k].parent;
+ }
+
+ idx = index[item];
+ items[items[idx].prevItem].nextItem = items[idx].nextItem;
+ items[items[idx].nextItem].prevItem = items[idx].prevItem;
+
+ }
+
+ /// \brief Moves the given element to another component.
+ ///
+ /// This method moves the element \e a from its component
+ /// to the component of \e comp.
+ /// If \e a and \e comp are in the same component then
+ /// it returns false otherwise it returns true.
+ bool move(const Item &item, const Item &comp) {
+ if (repIndex(index[item]) == repIndex(index[comp])) return false;
+ erase(item);
+ insert(item, comp);
+ return true;
}
- class ItemIt {
- friend class UnionFindEnum;
+ /// \brief Removes the component of the given element from the structure.
+ ///
+ /// Removes the component of the given element from the structure.
+ ///
+ /// \warning It is an error to give an element which is not in the
+ /// structure.
+ void eraseClass(const Item &item) {
+ unlaceClass(repIndex(index[item]));
+ }
- IcIter i;
- const ItemList *l;
+ /// \brief Lemon style iterator for the representant items.
+ ///
+ /// ClassIt is a lemon style iterator for the components. It iterates
+ /// on the representant items of the classes.
+ class ClassIt {
public:
- ItemIt(Invalid): l(0) {}
- ItemIt() {}
- ItemIt(UnionFindEnum const &ufe, const T& a) {
- l = &ufe.classOf(a);
- i = l->begin();
+ /// \brief Constructor of the iterator
+ ///
+ /// Constructor of the iterator
+ ClassIt(const UnionFindEnum& ufe) : unionFind(&ufe) {
+ idx = unionFind->firstClass;
}
+
+ /// \brief Constructor to get invalid iterator
+ ///
+ /// Constructor to get invalid iterator
+ ClassIt(Invalid) : unionFind(0), idx(-1) {}
- operator const T& () const { return i->me; }
- bool operator == (ItemIt const &it) const {
- return (l==it.l && i==it.i) || (!valid() && !it.valid());
- }
- bool operator != (ItemIt const &it) const {
- return !(*this == it);
+ /// \brief Increment operator
+ ///
+ /// It steps to the next representant item.
+ ClassIt& operator++() {
+ idx = unionFind->items[idx].nextClass;
+ return *this;
}
- bool operator < (ItemIt const &it) const {
- return (i < it.i);
+
+ /// \brief Conversion operator
+ ///
+ /// It converts the iterator to the current representant item.
+ operator const Item&() const {
+ return unionFind->items[idx].item;
+ }
+
+ /// \brief Equality operator
+ ///
+ /// Equality operator
+ bool operator==(const ClassIt& i) {
+ return i.idx == idx;
+ }
+
+ /// \brief Inequality operator
+ ///
+ /// Inequality operator
+ bool operator!=(const ClassIt& i) {
+ return i.idx != idx;
}
+
+ private:
+ const UnionFindEnum* unionFind;
+ int idx;
+ };
- bool operator==(Invalid) const {
- return !valid();
- }
- bool operator!=(Invalid) const {
- return valid();
+ /// \brief Lemon style iterator for the items of a component.
+ ///
+ /// ClassIt is a lemon style iterator for the components. It iterates
+ /// on the items of a class. By example if you want to iterate on
+ /// each items of each classes then you may write the next code.
+ ///\code
+ /// for (ClassIt cit(ufe); cit != INVALID; ++cit) {
+ /// std::cout << "Class: ";
+ /// for (ItemIt iit(ufe, cit); iit != INVALID; ++iit) {
+ /// std::cout << toString(iit) << ' ' << std::endl;
+ /// }
+ /// std::cout << std::endl;
+ /// }
+ ///\endcode
+ class ItemIt {
+ public:
+ /// \brief Constructor of the iterator
+ ///
+ /// Constructor of the iterator. The iterator iterates
+ /// on the class of the \c item.
+ ItemIt(const UnionFindEnum& ufe, const Item& item) : unionFind(&ufe) {
+ idx = unionFind->repIndex(unionFind->index[item]);
}
+ /// \brief Constructor to get invalid iterator
+ ///
+ /// Constructor to get invalid iterator
+ ItemIt(Invalid) : unionFind(0), idx(-1) {}
+
+ /// \brief Increment operator
+ ///
+ /// It steps to the next item in the class.
ItemIt& operator++() {
- ++i;
- return *this;
+ idx = unionFind->items[idx].nextItem;
+ if (unionFind->rep(idx)) idx = -1;
+ return *this;
}
-
- // obsoleted:
- bool valid() const { return l!=0 && i!=l->end(); }
+
+ /// \brief Conversion operator
+ ///
+ /// It converts the iterator to the current item.
+ operator const Item&() const {
+ return unionFind->items[idx].item;
+ }
+
+ /// \brief Equality operator
+ ///
+ /// Equality operator
+ bool operator==(const ItemIt& i) {
+ return i.idx == idx;
+ }
+
+ /// \brief Inequality operator
+ ///
+ /// Inequality operator
+ bool operator!=(const ItemIt& i) {
+ return i.idx != idx;
+ }
+
+ private:
+ const UnionFindEnum* unionFind;
+ int idx;
};
-
-
- /**
- * \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
- *
- * \bug obsoleted, use the new LEMON iterator interface instead
- */
-
- ItemIt& first(ItemIt& it, const T& a) const {
- it = ItemIt(*this, a);
- 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".
- *
- * \bug obsoleted, use the new LEMON iterator interface instead
- */
-
- 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".
- *
- * \bug obsoleted, use the new LEMON iterator interface instead
- */
-
- ItemIt& next(ItemIt& it) const {
- return ++it;
- }
-
};
Modified: hugo/trunk/test/unionfind_test.cc
==============================================================================
--- hugo/trunk/test/unionfind_test.cc (original)
+++ hugo/trunk/test/unionfind_test.cc Wed Sep 6 13:17:12 2006
@@ -25,19 +25,14 @@
using namespace lemon;
using namespace std;
-template <typename T>
-class BaseMap : public StdMap<int,T> {};
-
-typedef UnionFindEnum<int, BaseMap> UFE;
+typedef UnionFindEnum<int, StdMap<int, int> > UFE;
void print(UFE const &ufe) {
- UFE::ClassIt cit;
cout << "Print the classes of the structure:" << endl;
int i = 1;
- for (ufe.first(cit); ufe.valid(cit); ufe.next(cit)) {
+ for (UFE::ClassIt cit(ufe); cit != INVALID; ++cit) {
cout << " " << i << " (" << cit << "):" << flush;
- UFE::ItemIt iit;
- for (ufe.first(iit, cit); ufe.valid(iit); ufe.next(iit)) {
+ for (UFE::ItemIt iit(ufe, cit); iit != INVALID; ++iit) {
cout << " " << iit << flush;
}
cout << endl;
@@ -48,7 +43,7 @@
int main() {
- UFE::MapType base;
+ StdMap<int, int> base;
UFE U(base);
U.insert(1);
@@ -75,6 +70,7 @@
U.insert(9);
U.insert(10,9);
+
check(U.join(8,10),"Test failed.");
check(U.move(9,4),"Test failed.");
More information about the Lemon-commits
mailing list