00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00024
00025 #ifndef QVDISJOINTSET_H
00026 #define QVDISJOINTSET_H
00027
00028 #include <qvcore/qvimage.h>
00029
00030 #define INDEX(Col, Row) (Col*rows + Row)
00031
00032 namespace qvdta
00033 {
00148 class QVDisjointSet
00149 {
00150 public:
00157 QVDisjointSet(uInt numElements);
00158
00174 QVDisjointSet(uInt cols, uInt rows);
00175
00189 QVDisjointSet(QVGenericImage &image);
00190
00191 ~QVDisjointSet();
00192
00209 inline uInt find(QPoint p)
00210 {
00211 Q_ASSERT_X(cols > 0, "QVDisjointSet::find", "Number of columns equals 0");
00212 Q_ASSERT_X(rows > 0, "QVDisjointSet::find", "Number of rows equals 0");
00213
00215 Q_ASSERT_X(QRect(0,0,cols, rows).contains(p), "QVDisjointSet::find", "QPoint out of image bounds");
00216 return find(INDEX(p.x(), p.y()));
00217 }
00218
00237 inline uInt find(uInt col, uInt row)
00238 {
00239 Q_ASSERT_X(cols > 0, "QVDisjointSet::find", "Number of columns equals 0");
00240 Q_ASSERT_X(rows > 0, "QVDisjointSet::find", "Number of rows equals 0");
00241 Q_ASSERT_X(QRect(0,0,cols, rows).contains(QPoint(col, row)),
00242 "QVDisjointSet::find", "QPoint out of image bounds");
00243 return find(INDEX(col, row));
00244 }
00245
00263 inline uInt unify(QPoint p1, QPoint p2)
00264 {
00265 Q_ASSERT_X(cols > 0, "QVDisjointSet::unify", "Number of columns equals 0");
00266 Q_ASSERT_X(rows > 0, "QVDisjointSet::unify", "Number of rows equals 0");
00267 Q_ASSERT_X(QRect(0,0,cols, rows).contains(p1), "QVDisjointSet::unify", "First QPoint out of image bounds");
00268 Q_ASSERT_X(QRect(0,0,cols, rows).contains(p2), "QVDisjointSet::unify", "Second QPoint out of image bounds");
00269
00270 return unify(INDEX(p1.x(),p1.y()),INDEX(p2.x(),p2.y()));
00271 }
00272
00292 inline uInt unify(uInt c1, uInt r1, uInt c2, uInt r2)
00293 {
00294 Q_ASSERT_X(cols > 0, "QVDisjointSet::unify", "Number of columns equals 0");
00295 Q_ASSERT_X(rows > 0, "QVDisjointSet::unify", "Number of rows equals 0");
00296 Q_ASSERT_X(QRect(0,0,cols, rows).contains(QPoint(c1, r1)),
00297 "QVDisjointSet::unify", "First QPoint out of image bounds");
00298 Q_ASSERT_X(QRect(0,0,cols, rows).contains(QPoint(c2, r2)),
00299 "QVDisjointSet::unify", "Second QPoint out of image bounds");
00300
00301 return unify(INDEX(c1,r1),INDEX(c2,r2));
00302 }
00303
00308 inline uInt getSetCardinality(QPoint p1) { return getSetCardinality(INDEX(p1.x(), p1.y())); }
00309
00315 inline uInt getSetCardinality(uInt col, uInt row) { return getSetCardinality(INDEX(col, row)); }
00316
00322 inline uInt find(uInt index)
00323 {
00324 Q_ASSERT_X(index < elements, "QVDisjointSet::find", "Index exceeds number of elements");
00325
00326 if (parent[index] != index)
00327 parent[index] = find(parent[index]);
00328 return parent[index];
00329 }
00330
00339 uInt unify(uInt index1, uInt index2);
00340
00345 inline uInt getSetCardinality(uInt index)
00346 {
00347 Q_ASSERT(count[find(index)] > 0);
00348 return count[find(index)];
00349 }
00350
00354 inline uInt numberOfSets() { return sets; }
00355
00360 inline uInt index(QPoint p) { return INDEX(p.x(), p.y()); }
00361
00367 inline uInt index(uInt col, uInt row) { return INDEX(col, row); }
00368
00369 private:
00370 uInt elements, sets, cols, rows;
00371 uInt *parent, *rank, *count;
00372
00373 void makeSet();
00374 void allocData();
00375 void freeData();
00376 };
00377 }
00378 #endif