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