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