alpar@906
|
1 |
/* -*- C++ -*-
|
alpar@906
|
2 |
*
|
alpar@1956
|
3 |
* This file is a part of LEMON, a generic C++ optimization library
|
alpar@1956
|
4 |
*
|
alpar@2391
|
5 |
* Copyright (C) 2003-2007
|
alpar@1956
|
6 |
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
|
alpar@1359
|
7 |
* (Egervary Research Group on Combinatorial Optimization, EGRES).
|
alpar@906
|
8 |
*
|
alpar@906
|
9 |
* Permission to use, modify and distribute this software is granted
|
alpar@906
|
10 |
* provided that this copyright notice appears in all copies. For
|
alpar@906
|
11 |
* precise terms see the accompanying LICENSE file.
|
alpar@906
|
12 |
*
|
alpar@906
|
13 |
* This software is provided "AS IS" with no warranty of any kind,
|
alpar@906
|
14 |
* express or implied, and with no claim as to its suitability for any
|
alpar@906
|
15 |
* purpose.
|
alpar@906
|
16 |
*
|
alpar@906
|
17 |
*/
|
alpar@906
|
18 |
|
alpar@921
|
19 |
#ifndef LEMON_UNION_FIND_H
|
alpar@921
|
20 |
#define LEMON_UNION_FIND_H
|
beckerjc@483
|
21 |
|
klao@491
|
22 |
//!\ingroup auxdat
|
beckerjc@483
|
23 |
//!\file
|
beckerjc@483
|
24 |
//!\brief Union-Find data structures.
|
alpar@774
|
25 |
//!
|
beckerjc@483
|
26 |
|
beckerjc@483
|
27 |
#include <vector>
|
beckerjc@483
|
28 |
#include <list>
|
beckerjc@483
|
29 |
#include <utility>
|
beckerjc@483
|
30 |
#include <algorithm>
|
beckerjc@483
|
31 |
|
deba@1993
|
32 |
#include <lemon/bits/invalid.h>
|
beckerjc@483
|
33 |
|
alpar@921
|
34 |
namespace lemon {
|
beckerjc@483
|
35 |
|
deba@2308
|
36 |
/// \ingroup auxdat
|
deba@2308
|
37 |
///
|
deba@2205
|
38 |
/// \brief A \e Union-Find data structure implementation
|
deba@2205
|
39 |
///
|
deba@2205
|
40 |
/// The class implements the \e Union-Find data structure.
|
deba@2205
|
41 |
/// The union operation uses rank heuristic, while
|
deba@2205
|
42 |
/// the find operation uses path compression.
|
deba@2205
|
43 |
/// This is a very simple but efficient implementation, providing
|
deba@2205
|
44 |
/// only four methods: join (union), find, insert and size.
|
deba@2205
|
45 |
/// For more features see the \ref UnionFindEnum class.
|
deba@2205
|
46 |
///
|
deba@2205
|
47 |
/// It is primarily used in Kruskal algorithm for finding minimal
|
deba@2205
|
48 |
/// cost spanning tree in a graph.
|
deba@2205
|
49 |
/// \sa kruskal()
|
deba@2205
|
50 |
///
|
deba@2205
|
51 |
/// \pre You need to add all the elements by the \ref insert()
|
deba@2205
|
52 |
/// method.
|
deba@2308
|
53 |
template <typename _ItemIntMap>
|
beckerjc@483
|
54 |
class UnionFind {
|
beckerjc@483
|
55 |
public:
|
deba@2308
|
56 |
|
deba@2308
|
57 |
typedef _ItemIntMap ItemIntMap;
|
deba@2308
|
58 |
typedef typename ItemIntMap::Key Item;
|
beckerjc@483
|
59 |
|
beckerjc@483
|
60 |
private:
|
deba@2205
|
61 |
// If the items vector stores negative value for an item then
|
deba@2205
|
62 |
// that item is root item and it has -items[it] component size.
|
deba@2205
|
63 |
// Else the items[it] contains the index of the parent.
|
deba@2205
|
64 |
std::vector<int> items;
|
deba@2205
|
65 |
ItemIntMap& index;
|
deba@2205
|
66 |
|
deba@2205
|
67 |
bool rep(int idx) const {
|
deba@2205
|
68 |
return items[idx] < 0;
|
deba@2205
|
69 |
}
|
deba@2205
|
70 |
|
deba@2205
|
71 |
int repIndex(int idx) const {
|
deba@2205
|
72 |
int k = idx;
|
deba@2205
|
73 |
while (!rep(k)) {
|
deba@2205
|
74 |
k = items[k] ;
|
deba@2205
|
75 |
}
|
deba@2205
|
76 |
while (idx != k) {
|
deba@2205
|
77 |
int next = items[idx];
|
deba@2205
|
78 |
const_cast<int&>(items[idx]) = k;
|
deba@2205
|
79 |
idx = next;
|
deba@2205
|
80 |
}
|
deba@2205
|
81 |
return k;
|
deba@2205
|
82 |
}
|
beckerjc@483
|
83 |
|
beckerjc@483
|
84 |
public:
|
beckerjc@483
|
85 |
|
deba@2205
|
86 |
/// \brief Constructor
|
deba@2205
|
87 |
///
|
deba@2205
|
88 |
/// Constructor of the UnionFind class. You should give an item to
|
deba@2205
|
89 |
/// integer map which will be used from the data structure. If you
|
deba@2205
|
90 |
/// modify directly this map that may cause segmentation fault,
|
deba@2205
|
91 |
/// invalid data structure, or infinite loop when you use again
|
deba@2205
|
92 |
/// the union-find.
|
deba@2205
|
93 |
UnionFind(ItemIntMap& m) : index(m) {}
|
beckerjc@483
|
94 |
|
deba@2205
|
95 |
/// \brief Returns the index of the element's component.
|
deba@2205
|
96 |
///
|
deba@2205
|
97 |
/// The method returns the index of the element's component.
|
deba@2205
|
98 |
/// This is an integer between zero and the number of inserted elements.
|
deba@2205
|
99 |
///
|
deba@2205
|
100 |
int find(const Item& a) {
|
deba@2205
|
101 |
return repIndex(index[a]);
|
beckerjc@483
|
102 |
}
|
beckerjc@483
|
103 |
|
deba@2427
|
104 |
/// \brief Clears the union-find data structure
|
deba@2427
|
105 |
///
|
deba@2427
|
106 |
/// Erase each item from the data structure.
|
deba@2427
|
107 |
void clear() {
|
deba@2427
|
108 |
items.clear();
|
deba@2427
|
109 |
}
|
deba@2427
|
110 |
|
deba@2205
|
111 |
/// \brief Inserts a new element into the structure.
|
deba@2205
|
112 |
///
|
deba@2205
|
113 |
/// This method inserts a new element into the data structure.
|
deba@2205
|
114 |
///
|
deba@2205
|
115 |
/// The method returns the index of the new component.
|
deba@2205
|
116 |
int insert(const Item& a) {
|
deba@2205
|
117 |
int n = items.size();
|
deba@2205
|
118 |
items.push_back(-1);
|
deba@2205
|
119 |
index.set(a,n);
|
beckerjc@483
|
120 |
return n;
|
beckerjc@483
|
121 |
}
|
beckerjc@483
|
122 |
|
deba@2205
|
123 |
/// \brief Joining the components of element \e a and element \e b.
|
deba@2205
|
124 |
///
|
deba@2205
|
125 |
/// This is the \e union operation of the Union-Find structure.
|
deba@2205
|
126 |
/// Joins the component of element \e a and component of
|
deba@2205
|
127 |
/// element \e b. If \e a and \e b are in the same component then
|
deba@2205
|
128 |
/// it returns false otherwise it returns true.
|
deba@2205
|
129 |
bool join(const Item& a, const Item& b) {
|
deba@2205
|
130 |
int ka = repIndex(index[a]);
|
deba@2205
|
131 |
int kb = repIndex(index[b]);
|
beckerjc@483
|
132 |
|
deba@2205
|
133 |
if ( ka == kb )
|
beckerjc@483
|
134 |
return false;
|
beckerjc@483
|
135 |
|
deba@2205
|
136 |
if (items[ka] < items[kb]) {
|
deba@2205
|
137 |
items[ka] += items[kb];
|
deba@2205
|
138 |
items[kb] = ka;
|
deba@2205
|
139 |
} else {
|
deba@2205
|
140 |
items[kb] += items[ka];
|
deba@2205
|
141 |
items[ka] = kb;
|
beckerjc@483
|
142 |
}
|
beckerjc@483
|
143 |
return true;
|
beckerjc@483
|
144 |
}
|
beckerjc@483
|
145 |
|
deba@2205
|
146 |
/// \brief Returns the size of the component of element \e a.
|
deba@2205
|
147 |
///
|
deba@2205
|
148 |
/// Returns the size of the component of element \e a.
|
deba@2205
|
149 |
int size(const Item& a) {
|
deba@2205
|
150 |
int k = repIndex(index[a]);
|
deba@2205
|
151 |
return - items[k];
|
beckerjc@483
|
152 |
}
|
beckerjc@483
|
153 |
|
beckerjc@483
|
154 |
};
|
beckerjc@483
|
155 |
|
deba@2308
|
156 |
/// \ingroup auxdat
|
deba@2308
|
157 |
///
|
deba@2205
|
158 |
/// \brief A \e Union-Find data structure implementation which
|
deba@2205
|
159 |
/// is able to enumerate the components.
|
deba@2205
|
160 |
///
|
deba@2205
|
161 |
/// The class implements a \e Union-Find data structure
|
deba@2205
|
162 |
/// which is able to enumerate the components and the items in
|
deba@2205
|
163 |
/// a component. If you don't need this feature then perhaps it's
|
deba@2205
|
164 |
/// better to use the \ref UnionFind class which is more efficient.
|
deba@2205
|
165 |
///
|
deba@2205
|
166 |
/// The union operation uses rank heuristic, while
|
deba@2205
|
167 |
/// the find operation uses path compression.
|
deba@2205
|
168 |
///
|
deba@2205
|
169 |
/// \pre You need to add all the elements by the \ref insert()
|
deba@2205
|
170 |
/// method.
|
deba@2205
|
171 |
///
|
deba@2308
|
172 |
template <typename _ItemIntMap>
|
deba@2205
|
173 |
class UnionFindEnum {
|
deba@2205
|
174 |
public:
|
deba@2205
|
175 |
|
deba@2205
|
176 |
typedef _ItemIntMap ItemIntMap;
|
deba@2308
|
177 |
typedef typename ItemIntMap::Key Item;
|
deba@2308
|
178 |
|
deba@2205
|
179 |
private:
|
deba@2205
|
180 |
|
deba@2505
|
181 |
ItemIntMap& index;
|
deba@2505
|
182 |
|
deba@2205
|
183 |
// If the parent stores negative value for an item then that item
|
deba@2505
|
184 |
// is root item and it has ~(items[it].parent) component id. Else
|
deba@2205
|
185 |
// the items[it].parent contains the index of the parent.
|
deba@2205
|
186 |
//
|
deba@2505
|
187 |
// The \c next and \c prev provides the double-linked
|
deba@2505
|
188 |
// cyclic list of one component's items.
|
deba@2205
|
189 |
struct ItemT {
|
deba@2205
|
190 |
int parent;
|
deba@2205
|
191 |
Item item;
|
beckerjc@483
|
192 |
|
deba@2505
|
193 |
int next, prev;
|
deba@2205
|
194 |
};
|
beckerjc@483
|
195 |
|
deba@2205
|
196 |
std::vector<ItemT> items;
|
deba@2505
|
197 |
int firstFreeItem;
|
beckerjc@483
|
198 |
|
deba@2505
|
199 |
struct ClassT {
|
deba@2505
|
200 |
int size;
|
deba@2505
|
201 |
int firstItem;
|
deba@2505
|
202 |
int next, prev;
|
deba@2505
|
203 |
};
|
deba@2505
|
204 |
|
deba@2505
|
205 |
std::vector<ClassT> classes;
|
deba@2505
|
206 |
int firstClass, firstFreeClass;
|
deba@2505
|
207 |
|
deba@2505
|
208 |
int newClass() {
|
deba@2505
|
209 |
if (firstFreeClass == -1) {
|
deba@2505
|
210 |
int cdx = classes.size();
|
deba@2505
|
211 |
classes.push_back(ClassT());
|
deba@2505
|
212 |
return cdx;
|
deba@2505
|
213 |
} else {
|
deba@2505
|
214 |
int cdx = firstFreeClass;
|
deba@2505
|
215 |
firstFreeClass = classes[firstFreeClass].next;
|
deba@2505
|
216 |
return cdx;
|
deba@2505
|
217 |
}
|
deba@2505
|
218 |
}
|
deba@2505
|
219 |
|
deba@2505
|
220 |
int newItem() {
|
deba@2505
|
221 |
if (firstFreeItem == -1) {
|
deba@2505
|
222 |
int idx = items.size();
|
deba@2505
|
223 |
items.push_back(ItemT());
|
deba@2505
|
224 |
return idx;
|
deba@2505
|
225 |
} else {
|
deba@2505
|
226 |
int idx = firstFreeItem;
|
deba@2505
|
227 |
firstFreeItem = items[firstFreeItem].next;
|
deba@2505
|
228 |
return idx;
|
deba@2505
|
229 |
}
|
deba@2505
|
230 |
}
|
beckerjc@483
|
231 |
|
beckerjc@483
|
232 |
|
deba@2205
|
233 |
bool rep(int idx) const {
|
deba@2205
|
234 |
return items[idx].parent < 0;
|
beckerjc@483
|
235 |
}
|
beckerjc@483
|
236 |
|
deba@2205
|
237 |
int repIndex(int idx) const {
|
deba@2205
|
238 |
int k = idx;
|
deba@2205
|
239 |
while (!rep(k)) {
|
deba@2205
|
240 |
k = items[k].parent;
|
deba@2205
|
241 |
}
|
deba@2205
|
242 |
while (idx != k) {
|
deba@2205
|
243 |
int next = items[idx].parent;
|
deba@2205
|
244 |
const_cast<int&>(items[idx].parent) = k;
|
deba@2205
|
245 |
idx = next;
|
deba@2205
|
246 |
}
|
deba@2205
|
247 |
return k;
|
deba@2205
|
248 |
}
|
deba@2205
|
249 |
|
deba@2505
|
250 |
int classIndex(int idx) const {
|
deba@2505
|
251 |
return ~(items[repIndex(idx)].parent);
|
deba@2505
|
252 |
}
|
deba@2505
|
253 |
|
deba@2505
|
254 |
void singletonItem(int idx) {
|
deba@2505
|
255 |
items[idx].next = idx;
|
deba@2505
|
256 |
items[idx].prev = idx;
|
deba@2505
|
257 |
}
|
deba@2505
|
258 |
|
deba@2505
|
259 |
void laceItem(int idx, int rdx) {
|
deba@2505
|
260 |
items[idx].prev = rdx;
|
deba@2505
|
261 |
items[idx].next = items[rdx].next;
|
deba@2505
|
262 |
items[items[rdx].next].prev = idx;
|
deba@2505
|
263 |
items[rdx].next = idx;
|
deba@2505
|
264 |
}
|
deba@2505
|
265 |
|
deba@2505
|
266 |
void unlaceItem(int idx) {
|
deba@2505
|
267 |
items[items[idx].prev].next = items[idx].next;
|
deba@2505
|
268 |
items[items[idx].next].prev = items[idx].prev;
|
deba@2505
|
269 |
|
deba@2505
|
270 |
items[idx].next = firstFreeItem;
|
deba@2505
|
271 |
firstFreeItem = idx;
|
deba@2505
|
272 |
}
|
deba@2505
|
273 |
|
deba@2505
|
274 |
void spliceItems(int ak, int bk) {
|
deba@2505
|
275 |
items[items[ak].prev].next = bk;
|
deba@2505
|
276 |
items[items[bk].prev].next = ak;
|
deba@2505
|
277 |
int tmp = items[ak].prev;
|
deba@2505
|
278 |
items[ak].prev = items[bk].prev;
|
deba@2505
|
279 |
items[bk].prev = tmp;
|
deba@2505
|
280 |
|
deba@2505
|
281 |
}
|
deba@2505
|
282 |
|
deba@2505
|
283 |
void laceClass(int cls) {
|
deba@2505
|
284 |
if (firstClass != -1) {
|
deba@2505
|
285 |
classes[firstClass].prev = cls;
|
deba@2205
|
286 |
}
|
deba@2505
|
287 |
classes[cls].next = firstClass;
|
deba@2505
|
288 |
classes[cls].prev = -1;
|
deba@2505
|
289 |
firstClass = cls;
|
deba@2205
|
290 |
}
|
deba@2205
|
291 |
|
deba@2505
|
292 |
void unlaceClass(int cls) {
|
deba@2505
|
293 |
if (classes[cls].prev != -1) {
|
deba@2505
|
294 |
classes[classes[cls].prev].next = classes[cls].next;
|
deba@2505
|
295 |
} else {
|
deba@2505
|
296 |
firstClass = classes[cls].next;
|
deba@2505
|
297 |
}
|
deba@2505
|
298 |
if (classes[cls].next != -1) {
|
deba@2505
|
299 |
classes[classes[cls].next].prev = classes[cls].prev;
|
deba@2505
|
300 |
}
|
deba@2505
|
301 |
|
deba@2505
|
302 |
classes[cls].next = firstFreeClass;
|
deba@2505
|
303 |
firstFreeClass = cls;
|
deba@2505
|
304 |
}
|
klao@2003
|
305 |
|
beckerjc@483
|
306 |
public:
|
beckerjc@483
|
307 |
|
deba@2205
|
308 |
UnionFindEnum(ItemIntMap& _index)
|
deba@2505
|
309 |
: index(_index), items(), firstFreeItem(-1),
|
deba@2505
|
310 |
firstClass(-1), firstFreeClass(-1) {}
|
deba@2205
|
311 |
|
deba@2205
|
312 |
/// \brief Inserts the given element into a new component.
|
deba@2205
|
313 |
///
|
deba@2205
|
314 |
/// This method creates a new component consisting only of the
|
deba@2205
|
315 |
/// given element.
|
deba@2205
|
316 |
///
|
deba@2505
|
317 |
int insert(const Item& item) {
|
deba@2505
|
318 |
int idx = newItem();
|
beckerjc@483
|
319 |
|
deba@2205
|
320 |
index.set(item, idx);
|
beckerjc@483
|
321 |
|
deba@2505
|
322 |
singletonItem(idx);
|
deba@2505
|
323 |
items[idx].item = item;
|
deba@2505
|
324 |
|
deba@2505
|
325 |
int cdx = newClass();
|
deba@2505
|
326 |
|
deba@2505
|
327 |
items[idx].parent = ~cdx;
|
deba@2505
|
328 |
|
deba@2505
|
329 |
laceClass(cdx);
|
deba@2505
|
330 |
classes[cdx].size = 1;
|
deba@2505
|
331 |
classes[cdx].firstItem = idx;
|
deba@2505
|
332 |
|
deba@2505
|
333 |
firstClass = cdx;
|
deba@2205
|
334 |
|
deba@2505
|
335 |
return cdx;
|
beckerjc@483
|
336 |
}
|
beckerjc@483
|
337 |
|
deba@2205
|
338 |
/// \brief Inserts the given element into the component of the others.
|
deba@2205
|
339 |
///
|
deba@2205
|
340 |
/// This methods inserts the element \e a into the component of the
|
deba@2205
|
341 |
/// element \e comp.
|
deba@2505
|
342 |
void insert(const Item& item, int cls) {
|
deba@2505
|
343 |
int rdx = classes[cls].firstItem;
|
deba@2505
|
344 |
int idx = newItem();
|
beckerjc@483
|
345 |
|
deba@2205
|
346 |
index.set(item, idx);
|
deba@2205
|
347 |
|
deba@2505
|
348 |
laceItem(idx, rdx);
|
deba@2205
|
349 |
|
deba@2505
|
350 |
items[idx].item = item;
|
deba@2505
|
351 |
items[idx].parent = rdx;
|
deba@2205
|
352 |
|
deba@2505
|
353 |
++classes[~(items[rdx].parent)].size;
|
beckerjc@483
|
354 |
}
|
beckerjc@483
|
355 |
|
deba@2427
|
356 |
/// \brief Clears the union-find data structure
|
deba@2427
|
357 |
///
|
deba@2427
|
358 |
/// Erase each item from the data structure.
|
deba@2427
|
359 |
void clear() {
|
deba@2427
|
360 |
items.clear();
|
deba@2427
|
361 |
firstClass = -1;
|
deba@2505
|
362 |
firstFreeItem = -1;
|
deba@2427
|
363 |
}
|
deba@2427
|
364 |
|
deba@2505
|
365 |
/// \brief Finds the component of the given element.
|
deba@2205
|
366 |
///
|
deba@2505
|
367 |
/// The method returns the component id of the given element.
|
deba@2505
|
368 |
int find(const Item &item) const {
|
deba@2505
|
369 |
return ~(items[repIndex(index[item])].parent);
|
beckerjc@483
|
370 |
}
|
beckerjc@483
|
371 |
|
deba@2205
|
372 |
/// \brief Joining the component of element \e a and element \e b.
|
deba@2205
|
373 |
///
|
deba@2205
|
374 |
/// This is the \e union operation of the Union-Find structure.
|
deba@2205
|
375 |
/// Joins the component of element \e a and component of
|
deba@2205
|
376 |
/// element \e b. If \e a and \e b are in the same component then
|
deba@2505
|
377 |
/// returns -1 else returns the remaining class.
|
deba@2505
|
378 |
int join(const Item& a, const Item& b) {
|
beckerjc@483
|
379 |
|
deba@2205
|
380 |
int ak = repIndex(index[a]);
|
deba@2205
|
381 |
int bk = repIndex(index[b]);
|
beckerjc@483
|
382 |
|
deba@2205
|
383 |
if (ak == bk) {
|
deba@2505
|
384 |
return -1;
|
beckerjc@483
|
385 |
}
|
beckerjc@483
|
386 |
|
deba@2505
|
387 |
int acx = ~(items[ak].parent);
|
deba@2505
|
388 |
int bcx = ~(items[bk].parent);
|
deba@2505
|
389 |
|
deba@2505
|
390 |
int rcx;
|
deba@2505
|
391 |
|
deba@2505
|
392 |
if (classes[acx].size > classes[bcx].size) {
|
deba@2505
|
393 |
classes[acx].size += classes[bcx].size;
|
deba@2205
|
394 |
items[bk].parent = ak;
|
deba@2505
|
395 |
unlaceClass(bcx);
|
deba@2505
|
396 |
rcx = acx;
|
deba@2205
|
397 |
} else {
|
deba@2505
|
398 |
classes[bcx].size += classes[acx].size;
|
deba@2205
|
399 |
items[ak].parent = bk;
|
deba@2505
|
400 |
unlaceClass(acx);
|
deba@2505
|
401 |
rcx = bcx;
|
beckerjc@483
|
402 |
}
|
deba@2205
|
403 |
spliceItems(ak, bk);
|
beckerjc@483
|
404 |
|
deba@2505
|
405 |
return rcx;
|
beckerjc@483
|
406 |
}
|
beckerjc@483
|
407 |
|
deba@2505
|
408 |
/// \brief Returns the size of the class.
|
deba@2205
|
409 |
///
|
deba@2505
|
410 |
/// Returns the size of the class.
|
deba@2505
|
411 |
int size(int cls) const {
|
deba@2505
|
412 |
return classes[cls].size;
|
beckerjc@483
|
413 |
}
|
beckerjc@483
|
414 |
|
deba@2505
|
415 |
/// \brief Splits up the component.
|
deba@2205
|
416 |
///
|
deba@2505
|
417 |
/// Splitting the component into singleton components (component
|
deba@2505
|
418 |
/// of size one).
|
deba@2505
|
419 |
void split(int cls) {
|
deba@2505
|
420 |
int fdx = classes[cls].firstItem;
|
deba@2505
|
421 |
int idx = items[fdx].next;
|
deba@2505
|
422 |
while (idx != fdx) {
|
deba@2505
|
423 |
int next = items[idx].next;
|
deba@2505
|
424 |
|
deba@2505
|
425 |
singletonItem(idx);
|
deba@2505
|
426 |
|
deba@2505
|
427 |
int cdx = newClass();
|
deba@2505
|
428 |
items[idx].parent = ~cdx;
|
deba@2505
|
429 |
|
deba@2505
|
430 |
laceClass(cdx);
|
deba@2505
|
431 |
classes[cdx].size = 1;
|
deba@2505
|
432 |
classes[cdx].firstItem = idx;
|
deba@2205
|
433 |
|
deba@2205
|
434 |
idx = next;
|
beckerjc@483
|
435 |
}
|
beckerjc@483
|
436 |
|
deba@2505
|
437 |
items[idx].prev = idx;
|
deba@2505
|
438 |
items[idx].next = idx;
|
deba@2505
|
439 |
|
deba@2505
|
440 |
classes[~(items[idx].parent)].size = 1;
|
deba@2205
|
441 |
|
beckerjc@483
|
442 |
}
|
beckerjc@483
|
443 |
|
deba@2205
|
444 |
/// \brief Removes the given element from the structure.
|
deba@2205
|
445 |
///
|
deba@2205
|
446 |
/// Removes the element from its component and if the component becomes
|
deba@2205
|
447 |
/// empty then removes that component from the component list.
|
deba@2205
|
448 |
///
|
deba@2205
|
449 |
/// \warning It is an error to remove an element which is not in
|
deba@2205
|
450 |
/// the structure.
|
deba@2505
|
451 |
/// \warning This running time of this operation is proportional to the
|
deba@2505
|
452 |
/// number of the items in this class.
|
deba@2505
|
453 |
void erase(const Item& item) {
|
deba@2205
|
454 |
int idx = index[item];
|
deba@2505
|
455 |
int fdx = items[idx].next;
|
deba@2505
|
456 |
|
deba@2505
|
457 |
int cdx = classIndex(idx);
|
deba@2505
|
458 |
if (idx == fdx) {
|
deba@2505
|
459 |
unlaceClass(cdx);
|
deba@2505
|
460 |
items[idx].next = firstFreeItem;
|
deba@2505
|
461 |
firstFreeItem = idx;
|
deba@2505
|
462 |
return;
|
deba@2505
|
463 |
} else {
|
deba@2505
|
464 |
classes[cdx].firstItem = fdx;
|
deba@2505
|
465 |
--classes[cdx].size;
|
deba@2505
|
466 |
items[fdx].parent = ~cdx;
|
deba@2505
|
467 |
|
deba@2505
|
468 |
unlaceItem(idx);
|
deba@2505
|
469 |
idx = items[fdx].next;
|
deba@2505
|
470 |
while (idx != fdx) {
|
deba@2505
|
471 |
items[idx].parent = fdx;
|
deba@2505
|
472 |
idx = items[idx].next;
|
deba@2505
|
473 |
}
|
deba@2205
|
474 |
|
beckerjc@483
|
475 |
}
|
beckerjc@483
|
476 |
|
deba@2506
|
477 |
}
|
deba@2506
|
478 |
|
deba@2506
|
479 |
/// \brief Gives back a representant item of the component.
|
deba@2506
|
480 |
///
|
deba@2506
|
481 |
/// Gives back a representant item of the component.
|
deba@2506
|
482 |
Item item(int cls) const {
|
deba@2506
|
483 |
return items[classes[cls].firstItem].item;
|
deba@2506
|
484 |
}
|
beckerjc@483
|
485 |
|
deba@2205
|
486 |
/// \brief Removes the component of the given element from the structure.
|
deba@2205
|
487 |
///
|
deba@2205
|
488 |
/// Removes the component of the given element from the structure.
|
deba@2205
|
489 |
///
|
deba@2205
|
490 |
/// \warning It is an error to give an element which is not in the
|
deba@2205
|
491 |
/// structure.
|
deba@2505
|
492 |
void eraseClass(int cls) {
|
deba@2505
|
493 |
int fdx = classes[cls].firstItem;
|
deba@2505
|
494 |
unlaceClass(cls);
|
deba@2505
|
495 |
items[items[fdx].prev].next = firstFreeItem;
|
deba@2505
|
496 |
firstFreeItem = fdx;
|
deba@2205
|
497 |
}
|
beckerjc@483
|
498 |
|
deba@2205
|
499 |
/// \brief Lemon style iterator for the representant items.
|
deba@2205
|
500 |
///
|
deba@2205
|
501 |
/// ClassIt is a lemon style iterator for the components. It iterates
|
deba@2505
|
502 |
/// on the ids of the classes.
|
deba@2205
|
503 |
class ClassIt {
|
deba@2205
|
504 |
public:
|
deba@2205
|
505 |
/// \brief Constructor of the iterator
|
deba@2205
|
506 |
///
|
deba@2205
|
507 |
/// Constructor of the iterator
|
deba@2205
|
508 |
ClassIt(const UnionFindEnum& ufe) : unionFind(&ufe) {
|
deba@2505
|
509 |
cdx = unionFind->firstClass;
|
beckerjc@483
|
510 |
}
|
beckerjc@483
|
511 |
|
deba@2205
|
512 |
/// \brief Constructor to get invalid iterator
|
deba@2205
|
513 |
///
|
deba@2205
|
514 |
/// Constructor to get invalid iterator
|
deba@2505
|
515 |
ClassIt(Invalid) : unionFind(0), cdx(-1) {}
|
deba@2205
|
516 |
|
deba@2205
|
517 |
/// \brief Increment operator
|
deba@2205
|
518 |
///
|
deba@2205
|
519 |
/// It steps to the next representant item.
|
deba@2205
|
520 |
ClassIt& operator++() {
|
deba@2505
|
521 |
cdx = unionFind->classes[cdx].next;
|
deba@2205
|
522 |
return *this;
|
deba@2205
|
523 |
}
|
deba@2205
|
524 |
|
deba@2205
|
525 |
/// \brief Conversion operator
|
deba@2205
|
526 |
///
|
deba@2205
|
527 |
/// It converts the iterator to the current representant item.
|
deba@2505
|
528 |
operator int() const {
|
deba@2505
|
529 |
return cdx;
|
beckerjc@483
|
530 |
}
|
beckerjc@483
|
531 |
|
deba@2205
|
532 |
/// \brief Equality operator
|
deba@2205
|
533 |
///
|
deba@2205
|
534 |
/// Equality operator
|
deba@2205
|
535 |
bool operator==(const ClassIt& i) {
|
deba@2505
|
536 |
return i.cdx == cdx;
|
deba@2205
|
537 |
}
|
beckerjc@483
|
538 |
|
deba@2205
|
539 |
/// \brief Inequality operator
|
deba@2205
|
540 |
///
|
deba@2205
|
541 |
/// Inequality operator
|
deba@2205
|
542 |
bool operator!=(const ClassIt& i) {
|
deba@2505
|
543 |
return i.cdx != cdx;
|
klao@2003
|
544 |
}
|
beckerjc@483
|
545 |
|
deba@2205
|
546 |
private:
|
deba@2205
|
547 |
const UnionFindEnum* unionFind;
|
deba@2505
|
548 |
int cdx;
|
deba@2205
|
549 |
};
|
deba@2205
|
550 |
|
deba@2205
|
551 |
/// \brief Lemon style iterator for the items of a component.
|
deba@2205
|
552 |
///
|
deba@2205
|
553 |
/// ClassIt is a lemon style iterator for the components. It iterates
|
deba@2205
|
554 |
/// on the items of a class. By example if you want to iterate on
|
deba@2205
|
555 |
/// each items of each classes then you may write the next code.
|
deba@2205
|
556 |
///\code
|
deba@2205
|
557 |
/// for (ClassIt cit(ufe); cit != INVALID; ++cit) {
|
deba@2205
|
558 |
/// std::cout << "Class: ";
|
deba@2205
|
559 |
/// for (ItemIt iit(ufe, cit); iit != INVALID; ++iit) {
|
deba@2205
|
560 |
/// std::cout << toString(iit) << ' ' << std::endl;
|
deba@2205
|
561 |
/// }
|
deba@2205
|
562 |
/// std::cout << std::endl;
|
deba@2205
|
563 |
/// }
|
deba@2205
|
564 |
///\endcode
|
deba@2205
|
565 |
class ItemIt {
|
deba@2205
|
566 |
public:
|
deba@2205
|
567 |
/// \brief Constructor of the iterator
|
deba@2205
|
568 |
///
|
deba@2205
|
569 |
/// Constructor of the iterator. The iterator iterates
|
deba@2205
|
570 |
/// on the class of the \c item.
|
deba@2505
|
571 |
ItemIt(const UnionFindEnum& ufe, int cls) : unionFind(&ufe) {
|
deba@2505
|
572 |
fdx = idx = unionFind->classes[cls].firstItem;
|
beckerjc@483
|
573 |
}
|
beckerjc@483
|
574 |
|
deba@2205
|
575 |
/// \brief Constructor to get invalid iterator
|
deba@2205
|
576 |
///
|
deba@2205
|
577 |
/// Constructor to get invalid iterator
|
deba@2205
|
578 |
ItemIt(Invalid) : unionFind(0), idx(-1) {}
|
deba@2205
|
579 |
|
deba@2205
|
580 |
/// \brief Increment operator
|
deba@2205
|
581 |
///
|
deba@2205
|
582 |
/// It steps to the next item in the class.
|
deba@2205
|
583 |
ItemIt& operator++() {
|
deba@2505
|
584 |
idx = unionFind->items[idx].next;
|
deba@2505
|
585 |
if (idx == fdx) idx = -1;
|
deba@2205
|
586 |
return *this;
|
klao@2003
|
587 |
}
|
deba@2205
|
588 |
|
deba@2205
|
589 |
/// \brief Conversion operator
|
deba@2205
|
590 |
///
|
deba@2205
|
591 |
/// It converts the iterator to the current item.
|
deba@2205
|
592 |
operator const Item&() const {
|
deba@2205
|
593 |
return unionFind->items[idx].item;
|
klao@2003
|
594 |
}
|
klao@2003
|
595 |
|
deba@2205
|
596 |
/// \brief Equality operator
|
deba@2205
|
597 |
///
|
deba@2205
|
598 |
/// Equality operator
|
deba@2205
|
599 |
bool operator==(const ItemIt& i) {
|
deba@2205
|
600 |
return i.idx == idx;
|
klao@2003
|
601 |
}
|
klao@2003
|
602 |
|
deba@2205
|
603 |
/// \brief Inequality operator
|
deba@2205
|
604 |
///
|
deba@2205
|
605 |
/// Inequality operator
|
deba@2205
|
606 |
bool operator!=(const ItemIt& i) {
|
deba@2205
|
607 |
return i.idx != idx;
|
deba@2205
|
608 |
}
|
deba@2205
|
609 |
|
deba@2205
|
610 |
private:
|
deba@2205
|
611 |
const UnionFindEnum* unionFind;
|
deba@2505
|
612 |
int idx, fdx;
|
beckerjc@483
|
613 |
};
|
beckerjc@483
|
614 |
|
beckerjc@483
|
615 |
};
|
beckerjc@483
|
616 |
|
deba@2505
|
617 |
/// \ingroup auxdat
|
deba@2505
|
618 |
///
|
deba@2505
|
619 |
/// \brief A \e Extend-Find data structure implementation which
|
deba@2505
|
620 |
/// is able to enumerate the components.
|
deba@2505
|
621 |
///
|
deba@2505
|
622 |
/// The class implements an \e Extend-Find data structure which is
|
deba@2505
|
623 |
/// able to enumerate the components and the items in a
|
deba@2505
|
624 |
/// component. The data structure is a simplification of the
|
deba@2505
|
625 |
/// Union-Find structure, and it does not allow to merge two components.
|
deba@2505
|
626 |
///
|
deba@2505
|
627 |
/// \pre You need to add all the elements by the \ref insert()
|
deba@2505
|
628 |
/// method.
|
deba@2505
|
629 |
template <typename _ItemIntMap>
|
deba@2505
|
630 |
class ExtendFindEnum {
|
deba@2505
|
631 |
public:
|
deba@2505
|
632 |
|
deba@2505
|
633 |
typedef _ItemIntMap ItemIntMap;
|
deba@2505
|
634 |
typedef typename ItemIntMap::Key Item;
|
deba@2505
|
635 |
|
deba@2505
|
636 |
private:
|
deba@2505
|
637 |
|
deba@2505
|
638 |
ItemIntMap& index;
|
deba@2505
|
639 |
|
deba@2505
|
640 |
struct ItemT {
|
deba@2505
|
641 |
int cls;
|
deba@2505
|
642 |
Item item;
|
deba@2505
|
643 |
int next, prev;
|
deba@2505
|
644 |
};
|
deba@2505
|
645 |
|
deba@2505
|
646 |
std::vector<ItemT> items;
|
deba@2505
|
647 |
int firstFreeItem;
|
deba@2505
|
648 |
|
deba@2505
|
649 |
struct ClassT {
|
deba@2505
|
650 |
int firstItem;
|
deba@2505
|
651 |
int next, prev;
|
deba@2505
|
652 |
};
|
deba@2505
|
653 |
|
deba@2505
|
654 |
std::vector<ClassT> classes;
|
deba@2505
|
655 |
|
deba@2505
|
656 |
int firstClass, firstFreeClass;
|
deba@2505
|
657 |
|
deba@2505
|
658 |
int newClass() {
|
deba@2505
|
659 |
if (firstFreeClass != -1) {
|
deba@2505
|
660 |
int cdx = firstFreeClass;
|
deba@2505
|
661 |
firstFreeClass = classes[cdx].next;
|
deba@2505
|
662 |
return cdx;
|
deba@2505
|
663 |
} else {
|
deba@2505
|
664 |
classes.push_back(ClassT());
|
deba@2505
|
665 |
return classes.size() - 1;
|
deba@2505
|
666 |
}
|
deba@2505
|
667 |
}
|
deba@2505
|
668 |
|
deba@2505
|
669 |
int newItem() {
|
deba@2505
|
670 |
if (firstFreeItem != -1) {
|
deba@2505
|
671 |
int idx = firstFreeItem;
|
deba@2505
|
672 |
firstFreeItem = items[idx].next;
|
deba@2505
|
673 |
return idx;
|
deba@2505
|
674 |
} else {
|
deba@2505
|
675 |
items.push_back(ItemT());
|
deba@2505
|
676 |
return items.size() - 1;
|
deba@2505
|
677 |
}
|
deba@2505
|
678 |
}
|
deba@2505
|
679 |
|
deba@2505
|
680 |
public:
|
deba@2505
|
681 |
|
deba@2505
|
682 |
/// \brief Constructor
|
deba@2505
|
683 |
ExtendFindEnum(ItemIntMap& _index)
|
deba@2505
|
684 |
: index(_index), items(), firstFreeItem(-1),
|
deba@2505
|
685 |
classes(), firstClass(-1), firstFreeClass(-1) {}
|
deba@2505
|
686 |
|
deba@2505
|
687 |
/// \brief Inserts the given element into a new component.
|
deba@2505
|
688 |
///
|
deba@2505
|
689 |
/// This method creates a new component consisting only of the
|
deba@2505
|
690 |
/// given element.
|
deba@2505
|
691 |
int insert(const Item& item) {
|
deba@2505
|
692 |
int cdx = newClass();
|
deba@2505
|
693 |
classes[cdx].prev = -1;
|
deba@2505
|
694 |
classes[cdx].next = firstClass;
|
deba@2505
|
695 |
firstClass = cdx;
|
deba@2505
|
696 |
|
deba@2505
|
697 |
int idx = newItem();
|
deba@2505
|
698 |
items[idx].item = item;
|
deba@2505
|
699 |
items[idx].cls = cdx;
|
deba@2505
|
700 |
items[idx].prev = idx;
|
deba@2505
|
701 |
items[idx].next = idx;
|
deba@2505
|
702 |
|
deba@2505
|
703 |
classes[cdx].firstItem = idx;
|
deba@2505
|
704 |
|
deba@2505
|
705 |
index.set(item, idx);
|
deba@2505
|
706 |
|
deba@2505
|
707 |
return cdx;
|
deba@2505
|
708 |
}
|
deba@2505
|
709 |
|
deba@2505
|
710 |
/// \brief Inserts the given element into the given component.
|
deba@2505
|
711 |
///
|
deba@2505
|
712 |
/// This methods inserts the element \e item a into the \e cls class.
|
deba@2505
|
713 |
void insert(const Item& item, int cls) {
|
deba@2505
|
714 |
int idx = newItem();
|
deba@2505
|
715 |
int rdx = classes[cls].firstItem;
|
deba@2505
|
716 |
items[idx].item = item;
|
deba@2505
|
717 |
items[idx].cls = cls;
|
deba@2505
|
718 |
|
deba@2505
|
719 |
items[idx].prev = rdx;
|
deba@2505
|
720 |
items[idx].next = items[rdx].next;
|
deba@2505
|
721 |
items[items[rdx].next].prev = idx;
|
deba@2505
|
722 |
items[rdx].next = idx;
|
deba@2505
|
723 |
|
deba@2505
|
724 |
index.set(item, idx);
|
deba@2505
|
725 |
}
|
deba@2505
|
726 |
|
deba@2505
|
727 |
/// \brief Clears the union-find data structure
|
deba@2505
|
728 |
///
|
deba@2505
|
729 |
/// Erase each item from the data structure.
|
deba@2505
|
730 |
void clear() {
|
deba@2505
|
731 |
items.clear();
|
deba@2505
|
732 |
classes.clear;
|
deba@2505
|
733 |
firstClass = firstFreeClass = firstFreeItem = -1;
|
deba@2505
|
734 |
}
|
deba@2505
|
735 |
|
deba@2505
|
736 |
/// \brief Gives back the class of the \e item.
|
deba@2505
|
737 |
///
|
deba@2505
|
738 |
/// Gives back the class of the \e item.
|
deba@2505
|
739 |
int find(const Item &item) const {
|
deba@2505
|
740 |
return items[index[item]].cls;
|
deba@2505
|
741 |
}
|
deba@2506
|
742 |
|
deba@2506
|
743 |
/// \brief Gives back a representant item of the component.
|
deba@2506
|
744 |
///
|
deba@2506
|
745 |
/// Gives back a representant item of the component.
|
deba@2506
|
746 |
Item item(int cls) const {
|
deba@2506
|
747 |
return items[classes[cls].firstItem].item;
|
deba@2506
|
748 |
}
|
deba@2505
|
749 |
|
deba@2505
|
750 |
/// \brief Removes the given element from the structure.
|
deba@2505
|
751 |
///
|
deba@2505
|
752 |
/// Removes the element from its component and if the component becomes
|
deba@2505
|
753 |
/// empty then removes that component from the component list.
|
deba@2505
|
754 |
///
|
deba@2505
|
755 |
/// \warning It is an error to remove an element which is not in
|
deba@2505
|
756 |
/// the structure.
|
deba@2505
|
757 |
void erase(const Item &item) {
|
deba@2505
|
758 |
int idx = index[item];
|
deba@2505
|
759 |
int cdx = items[idx].cls;
|
deba@2505
|
760 |
|
deba@2505
|
761 |
if (idx == items[idx].next) {
|
deba@2505
|
762 |
if (classes[cdx].prev != -1) {
|
deba@2505
|
763 |
classes[classes[cdx].prev].next = classes[cdx].next;
|
deba@2505
|
764 |
} else {
|
deba@2505
|
765 |
firstClass = classes[cdx].next;
|
deba@2505
|
766 |
}
|
deba@2505
|
767 |
if (classes[cdx].next != -1) {
|
deba@2505
|
768 |
classes[classes[cdx].next].prev = classes[cdx].prev;
|
deba@2505
|
769 |
}
|
deba@2505
|
770 |
classes[cdx].next = firstFreeClass;
|
deba@2505
|
771 |
firstFreeClass = cdx;
|
deba@2505
|
772 |
} else {
|
deba@2505
|
773 |
classes[cdx].firstItem = items[idx].next;
|
deba@2505
|
774 |
items[items[idx].next].prev = items[idx].prev;
|
deba@2505
|
775 |
items[items[idx].prev].next = items[idx].next;
|
deba@2505
|
776 |
}
|
deba@2505
|
777 |
items[idx].next = firstFreeItem;
|
deba@2505
|
778 |
firstFreeItem = idx;
|
deba@2505
|
779 |
|
deba@2505
|
780 |
}
|
deba@2505
|
781 |
|
deba@2505
|
782 |
|
deba@2505
|
783 |
/// \brief Removes the component of the given element from the structure.
|
deba@2505
|
784 |
///
|
deba@2505
|
785 |
/// Removes the component of the given element from the structure.
|
deba@2505
|
786 |
///
|
deba@2505
|
787 |
/// \warning It is an error to give an element which is not in the
|
deba@2505
|
788 |
/// structure.
|
deba@2505
|
789 |
void eraseClass(int cdx) {
|
deba@2505
|
790 |
int idx = classes[cdx].firstItem;
|
deba@2505
|
791 |
items[items[idx].prev].next = firstFreeItem;
|
deba@2505
|
792 |
firstFreeItem = idx;
|
deba@2505
|
793 |
|
deba@2505
|
794 |
if (classes[cdx].prev != -1) {
|
deba@2505
|
795 |
classes[classes[cdx].prev].next = classes[cdx].next;
|
deba@2505
|
796 |
} else {
|
deba@2505
|
797 |
firstClass = classes[cdx].next;
|
deba@2505
|
798 |
}
|
deba@2505
|
799 |
if (classes[cdx].next != -1) {
|
deba@2505
|
800 |
classes[classes[cdx].next].prev = classes[cdx].prev;
|
deba@2505
|
801 |
}
|
deba@2505
|
802 |
classes[cdx].next = firstFreeClass;
|
deba@2505
|
803 |
firstFreeClass = cdx;
|
deba@2505
|
804 |
}
|
deba@2505
|
805 |
|
deba@2505
|
806 |
/// \brief Lemon style iterator for the classes.
|
deba@2505
|
807 |
///
|
deba@2505
|
808 |
/// ClassIt is a lemon style iterator for the components. It iterates
|
deba@2505
|
809 |
/// on the ids of classes.
|
deba@2505
|
810 |
class ClassIt {
|
deba@2505
|
811 |
public:
|
deba@2505
|
812 |
/// \brief Constructor of the iterator
|
deba@2505
|
813 |
///
|
deba@2505
|
814 |
/// Constructor of the iterator
|
deba@2505
|
815 |
ClassIt(const ExtendFindEnum& ufe) : extendFind(&ufe) {
|
deba@2505
|
816 |
cdx = extendFind->firstClass;
|
deba@2505
|
817 |
}
|
deba@2505
|
818 |
|
deba@2505
|
819 |
/// \brief Constructor to get invalid iterator
|
deba@2505
|
820 |
///
|
deba@2505
|
821 |
/// Constructor to get invalid iterator
|
deba@2505
|
822 |
ClassIt(Invalid) : extendFind(0), cdx(-1) {}
|
deba@2505
|
823 |
|
deba@2505
|
824 |
/// \brief Increment operator
|
deba@2505
|
825 |
///
|
deba@2505
|
826 |
/// It steps to the next representant item.
|
deba@2505
|
827 |
ClassIt& operator++() {
|
deba@2505
|
828 |
cdx = extendFind->classes[cdx].next;
|
deba@2505
|
829 |
return *this;
|
deba@2505
|
830 |
}
|
deba@2505
|
831 |
|
deba@2505
|
832 |
/// \brief Conversion operator
|
deba@2505
|
833 |
///
|
deba@2505
|
834 |
/// It converts the iterator to the current class id.
|
deba@2505
|
835 |
operator int() const {
|
deba@2505
|
836 |
return cdx;
|
deba@2505
|
837 |
}
|
deba@2505
|
838 |
|
deba@2505
|
839 |
/// \brief Equality operator
|
deba@2505
|
840 |
///
|
deba@2505
|
841 |
/// Equality operator
|
deba@2505
|
842 |
bool operator==(const ClassIt& i) {
|
deba@2505
|
843 |
return i.cdx == cdx;
|
deba@2505
|
844 |
}
|
deba@2505
|
845 |
|
deba@2505
|
846 |
/// \brief Inequality operator
|
deba@2505
|
847 |
///
|
deba@2505
|
848 |
/// Inequality operator
|
deba@2505
|
849 |
bool operator!=(const ClassIt& i) {
|
deba@2505
|
850 |
return i.cdx != cdx;
|
deba@2505
|
851 |
}
|
deba@2505
|
852 |
|
deba@2505
|
853 |
private:
|
deba@2505
|
854 |
const ExtendFindEnum* extendFind;
|
deba@2505
|
855 |
int cdx;
|
deba@2505
|
856 |
};
|
deba@2505
|
857 |
|
deba@2505
|
858 |
/// \brief Lemon style iterator for the items of a component.
|
deba@2505
|
859 |
///
|
deba@2505
|
860 |
/// ClassIt is a lemon style iterator for the components. It iterates
|
deba@2505
|
861 |
/// on the items of a class. By example if you want to iterate on
|
deba@2505
|
862 |
/// each items of each classes then you may write the next code.
|
deba@2505
|
863 |
///\code
|
deba@2505
|
864 |
/// for (ClassIt cit(ufe); cit != INVALID; ++cit) {
|
deba@2505
|
865 |
/// std::cout << "Class: ";
|
deba@2505
|
866 |
/// for (ItemIt iit(ufe, cit); iit != INVALID; ++iit) {
|
deba@2505
|
867 |
/// std::cout << toString(iit) << ' ' << std::endl;
|
deba@2505
|
868 |
/// }
|
deba@2505
|
869 |
/// std::cout << std::endl;
|
deba@2505
|
870 |
/// }
|
deba@2505
|
871 |
///\endcode
|
deba@2505
|
872 |
class ItemIt {
|
deba@2505
|
873 |
public:
|
deba@2505
|
874 |
/// \brief Constructor of the iterator
|
deba@2505
|
875 |
///
|
deba@2505
|
876 |
/// Constructor of the iterator. The iterator iterates
|
deba@2505
|
877 |
/// on the class of the \c item.
|
deba@2505
|
878 |
ItemIt(const ExtendFindEnum& ufe, int cls) : extendFind(&ufe) {
|
deba@2505
|
879 |
fdx = idx = extendFind->classes[cls].firstItem;
|
deba@2505
|
880 |
}
|
deba@2505
|
881 |
|
deba@2505
|
882 |
/// \brief Constructor to get invalid iterator
|
deba@2505
|
883 |
///
|
deba@2505
|
884 |
/// Constructor to get invalid iterator
|
deba@2505
|
885 |
ItemIt(Invalid) : extendFind(0), idx(-1) {}
|
deba@2505
|
886 |
|
deba@2505
|
887 |
/// \brief Increment operator
|
deba@2505
|
888 |
///
|
deba@2505
|
889 |
/// It steps to the next item in the class.
|
deba@2505
|
890 |
ItemIt& operator++() {
|
deba@2505
|
891 |
idx = extendFind->items[idx].next;
|
deba@2505
|
892 |
if (fdx == idx) idx = -1;
|
deba@2505
|
893 |
return *this;
|
deba@2505
|
894 |
}
|
deba@2505
|
895 |
|
deba@2505
|
896 |
/// \brief Conversion operator
|
deba@2505
|
897 |
///
|
deba@2505
|
898 |
/// It converts the iterator to the current item.
|
deba@2505
|
899 |
operator const Item&() const {
|
deba@2505
|
900 |
return extendFind->items[idx].item;
|
deba@2505
|
901 |
}
|
deba@2505
|
902 |
|
deba@2505
|
903 |
/// \brief Equality operator
|
deba@2505
|
904 |
///
|
deba@2505
|
905 |
/// Equality operator
|
deba@2505
|
906 |
bool operator==(const ItemIt& i) {
|
deba@2505
|
907 |
return i.idx == idx;
|
deba@2505
|
908 |
}
|
deba@2505
|
909 |
|
deba@2505
|
910 |
/// \brief Inequality operator
|
deba@2505
|
911 |
///
|
deba@2505
|
912 |
/// Inequality operator
|
deba@2505
|
913 |
bool operator!=(const ItemIt& i) {
|
deba@2505
|
914 |
return i.idx != idx;
|
deba@2505
|
915 |
}
|
deba@2505
|
916 |
|
deba@2505
|
917 |
private:
|
deba@2505
|
918 |
const ExtendFindEnum* extendFind;
|
deba@2505
|
919 |
int idx, fdx;
|
deba@2505
|
920 |
};
|
deba@2505
|
921 |
|
deba@2505
|
922 |
};
|
beckerjc@483
|
923 |
|
beckerjc@483
|
924 |
//! @}
|
beckerjc@483
|
925 |
|
alpar@921
|
926 |
} //namespace lemon
|
beckerjc@483
|
927 |
|
alpar@921
|
928 |
#endif //LEMON_UNION_FIND_H
|