41#define OGDF_DISJOINT_SETS_INTERMEDIATE_PARENT_CHECK
71namespace disjoint_sets {
75template<LinkOptions linkOption>
78template<CompressionOptions compressionOption>
81template<InterleavingOptions
interleavingOption>
92 "Rem's Algorithm requires linking by index.");
94 "Tarjan and van Leeuwen's Algorithm requires linking by rank.");
97 "Interleaved Reversal Type 0 requires naïve linking.");
100 "Interleaved Path Splitting Path Compression requires linking by index.");
148 init(maxNumberOfElements);
160 if (copy.m_parents) {
163 if (copy.m_parameters) {
166 if (copy.m_siblings) {
172 std::swap(first.m_numberOfSets, second.m_numberOfSets);
173 std::swap(first.m_numberOfElements, second.m_numberOfElements);
174 std::swap(first.m_maxNumberOfElements, second.m_maxNumberOfElements);
175 std::swap(first.m_parents, second.m_parents);
176 std::swap(first.m_parameters, second.m_parameters);
177 std::swap(first.m_siblings, second.m_siblings);
183 void
init(
int maxNumberOfElements) {
184 this->m_maxNumberOfElements = maxNumberOfElements;
193 this->m_numberOfSets = 0;
194 this->m_numberOfElements = 0;
197 ?
new int[this->m_maxNumberOfElements]
200 ?
new int[this->m_maxNumberOfElements]
236 if (this->m_numberOfElements == this->m_maxNumberOfElements) {
238 this->m_parents =
new int[this->m_maxNumberOfElements * 2];
239 memcpy(this->m_parents, parents,
sizeof(
int) * this->m_maxNumberOfElements);
242 if (this->m_parameters !=
nullptr) {
244 this->m_parameters =
new int[this->m_maxNumberOfElements * 2];
245 memcpy(this->m_parameters, parameters,
sizeof(
int) * this->m_maxNumberOfElements);
249 if (this->m_siblings !=
nullptr) {
251 this->m_siblings =
new int[this->m_maxNumberOfElements * 2];
252 memcpy(this->m_siblings, siblings,
sizeof(
int) * this->m_maxNumberOfElements);
255 this->m_maxNumberOfElements *= 2;
257 this->m_numberOfSets++;
258 int id = this->m_numberOfElements++;
259 this->m_parents[id] = id;
262 this->m_parameters[id] = 1;
264 this->m_parameters[id] = 0;
267 this->m_siblings[id] = -1;
283 this->m_numberOfSets--;
317 int subset = set1 == superset ? set2 : set1;
319 while (this->m_siblings[
id] != -1) {
320 id = this->m_siblings[id];
321 this->m_parents[id] = superset;
323 this->m_siblings[id] = this->m_siblings[superset];
324 this->m_siblings[superset] = subset;
331template<LinkOptions linkOption, CompressionOptions compressionOption, InterleavingOptions
interleavingOption>
334 int parent = m_parents[set];
340 m_parents[set] = parent;
345template<LinkOptions linkOption, CompressionOptions compressionOption, InterleavingOptions
interleavingOption>
348 while (set != m_parents[set]) {
349 int parent = m_parents[set];
350 int grandParent = m_parents[parent];
351 m_parents[set] = grandParent;
357template<LinkOptions linkOption, CompressionOptions compressionOption, InterleavingOptions
interleavingOption>
360 int parent = m_parents[set];
361 int grandParent = m_parents[parent];
362 while (parent != grandParent) {
363 m_parents[set] = grandParent;
365 parent = grandParent;
366 grandParent = m_parents[grandParent];
371template<LinkOptions linkOption, CompressionOptions compressionOption, InterleavingOptions
interleavingOption>
375 set = m_parents[root];
377 while (set != m_parents[set]) {
378 int parent = m_parents[set];
379 m_parents[set] = root;
382 m_parents[root] = set;
386template<LinkOptions linkOption, CompressionOptions compressionOption, InterleavingOptions
interleavingOption>
389 while (set != m_parents[set]) {
390 set = m_parents[set];
395template<LinkOptions linkOption, CompressionOptions compressionOption, InterleavingOptions
interleavingOption>
398 return m_parents[set];
402template<LinkOptions linkOption, CompressionOptions compressionOption, InterleavingOptions
interleavingOption>
405 int set1,
int set2) {
406#ifdef OGDF_DISJOINT_SETS_INTERMEDIATE_PARENT_CHECK
407 if (m_parents[set1] == m_parents[set2]) {
414 linkPure(set1, set2);
420template<LinkOptions linkOption, CompressionOptions compressionOption, InterleavingOptions
interleavingOption>
424#ifdef OGDF_DISJOINT_SETS_INTERMEDIATE_PARENT_CHECK
425 if (m_parents[set1] == m_parents[set2]) {
431 int parent = m_parents[set];
432 m_parents[set] = root;
433 while (set != parent) {
434 if (parent == set1) {
435 m_parents[root] = set1;
439 parent = m_parents[set];
440 m_parents[set] = root;
444 parent = m_parents[set];
446 if (parent == root) {
449 m_parents[set] = root;
454 parent = m_parents[set];
458template<LinkOptions linkOption, CompressionOptions compressionOption, InterleavingOptions
interleavingOption>
464 int p_r_x = m_parents[r_x];
465 int p_r_y = m_parents[r_y];
466 while (p_r_x != p_r_y) {
469 m_parents[r_x] = p_r_y;
472 m_parents[r_x] = p_r_y;
474 p_r_x = m_parents[r_x];
477 m_parents[r_y] = p_r_x;
480 m_parents[r_y] = p_r_x;
482 p_r_y = m_parents[r_y];
488template<LinkOptions linkOption, CompressionOptions compressionOption, InterleavingOptions
interleavingOption>
493#ifdef OGDF_DISJOINT_SETS_INTERMEDIATE_PARENT_CHECK
494 if (m_parents[set1] == m_parents[set2]) {
507 set = m_parents[set];
508 int parent = m_parents[set];
509 int grandParent = m_parents[parent];
510 while (parent != grandParent) {
511 m_parents[set] = grandParent;
513 parent = grandParent;
514 grandParent = m_parents[grandParent];
516 m_parents[set1] = parent;
521 parent = m_parents[set];
524 m_parents[set] = root;
529 parent = m_parents[set];
530 }
else if (parent > root) {
531 m_parents[root] = parent;
532 m_parents[set1] = parent;
533 m_parents[set2] = parent;
541template<LinkOptions linkOption, CompressionOptions compressionOption, InterleavingOptions
interleavingOption>
547 int p_r_x = m_parents[r_x];
548 int p_r_y = m_parents[r_y];
549 while (p_r_x != p_r_y) {
550 if (m_parameters[p_r_x] <= m_parameters[p_r_y]) {
552 if (m_parameters[p_r_x] == m_parameters[p_r_y] && p_r_y == m_parents[p_r_y]) {
553 m_parameters[p_r_y]++;
555 m_parents[r_x] = m_parents[p_r_y];
558 m_parents[r_x] = p_r_y;
560 p_r_x = m_parents[r_x];
563 m_parents[r_y] = m_parents[p_r_x];
566 m_parents[r_y] = p_r_x;
568 p_r_y = m_parents[r_y];
575template<LinkOptions linkOption, CompressionOptions compressionOption, InterleavingOptions
interleavingOption>
579 m_parents[set1] = set2;
582 m_parents[set2] = set1;
587template<LinkOptions linkOption, CompressionOptions compressionOption, InterleavingOptions
interleavingOption>
590 int parameter1 = m_parameters[set1];
591 int parameter2 = m_parameters[set2];
593 if (parameter1 < parameter2) {
594 m_parents[set1] = set2;
596 }
else if (parameter1 > parameter2) {
597 m_parents[set2] = set1;
600 m_parents[set1] = set2;
601 m_parameters[set2]++;
606template<LinkOptions linkOption, CompressionOptions compressionOption, InterleavingOptions
interleavingOption>
609 int parameter1 = m_parameters[set1];
610 int parameter2 = m_parameters[set2];
612 if (parameter1 < parameter2) {
613 m_parents[set1] = set2;
614 m_parameters[set2] += parameter1;
617 m_parents[set2] = set1;
618 m_parameters[set1] += parameter2;
623template<LinkOptions linkOption, CompressionOptions compressionOption, InterleavingOptions
interleavingOption>
626 m_parents[set1] = set2;
Basic declarations, included by all source files.
A Union/Find data structure for maintaining disjoint sets.
bool quickUnion(int set1, int set2)
Unions the maximal disjoint sets containing set1 and set2.
int makeSet()
Initializes a singleton set.
int getRepresentative(int set) const
Returns the id of the largest superset of set.
void init()
Resets the DisjointSets structure to be empty, preserving the previous value of maxNumberOfElements.
int m_numberOfElements
Current number of elements.
bool quickUnion(disjoint_sets::LinkOption< LinkOptions::Index >, disjoint_sets::InterleavingOption< InterleavingOptions::Rem >, int set1, int set2)
int find(int set)
Returns the id of the largest superset of set and compresses the path according to CompressionOptions...
int m_numberOfSets
Current number of disjoint sets.
int getNumberOfSets()
Returns the current number of disjoint sets.
int find(disjoint_sets::CompressionOption< CompressionOptions::PathCompression >, int set)
int link(disjoint_sets::LinkOption< LinkOptions::Naive >, int set1, int set2)
DisjointSets(int maxNumberOfElements=(1<< 15))
Creates an empty DisjointSets structure.
int * m_parameters
Maps set id to rank/size.
int getNumberOfElements()
Returns the current number of elements.
int * m_parents
Maps set id to parent set id.
int link(int set1, int set2)
Unions set1 and set2.
int linkPure(int set1, int set2)
Unions set1 and set2 w/o decreasing the numberOfSets.
int * m_siblings
Maps set id to sibling set id.
int m_maxNumberOfElements
Maximum number of elements (array size) adjusted dynamically.
Utility macros for declaring copy and move constructors and assignment operations.
#define OGDF_COPY_CONSTR(cls)
Declares the copy constructor for class cls.
#define OGDF_SWAP_OP(cls)
Declares the swap function for class cls.
#define OGDF_COPY_MOVE_BY_SWAP(cls)
Provide move construct/assign and copy assign given there is a copy constructor and swap.
#define OGDF_ASSERT(expr)
Assert condition expr. See doc/build.md for more information.
The namespace for all OGDF objects.
LinkOptions
Defines options for linking two sets.
@ Index
Link by index (default)
InterleavingOptions
Defines options for interleaving find/link operations in quickUnion.
@ Type0Reversal
Interleaved Reversal of Type 0 (only compatible with LinkOptions::Naive)
@ SplittingCompression
Interleaved Path Splitting Path Compression (only compatible with LinkOptions::Index)
@ Tarjan
Tarjan's and van Leeuwen's Algorithm (only compatible with LinkOptions::Rank)
@ Disabled
No Interleaving (default)
@ Rem
Rem's Algorithm (only compatible with LinkOptions::Index)
CompressionOptions
Defines options for compression search paths.
@ PathHalving
Path Halving.
@ PathSplitting
Path Splitting (default)
@ Disabled
No Compression.
@ Type1Reversal
Reversal of type 1.
@ PathCompression
Path Compression.