|
|
|
|
|
#ifndef DLIB_DISJOINT_SUBsETS_Hh_ |
|
#define DLIB_DISJOINT_SUBsETS_Hh_ |
|
|
|
#include "disjoint_subsets_abstract.h" |
|
#include <vector> |
|
#include "../algs.h" |
|
|
|
namespace dlib |
|
{ |
|
|
|
|
|
|
|
class disjoint_subsets |
|
{ |
|
public: |
|
|
|
void clear ( |
|
) noexcept |
|
{ |
|
items.clear(); |
|
} |
|
|
|
void set_size ( |
|
unsigned long new_size |
|
) |
|
{ |
|
items.resize(new_size); |
|
for (unsigned long i = 0; i < items.size(); ++i) |
|
{ |
|
items[i].parent = i; |
|
items[i].rank = 0; |
|
} |
|
} |
|
|
|
size_t size ( |
|
) const noexcept |
|
{ |
|
return items.size(); |
|
} |
|
|
|
unsigned long find_set ( |
|
unsigned long item |
|
) const |
|
{ |
|
|
|
DLIB_ASSERT(item < size(), |
|
"\t unsigned long disjoint_subsets::find_set()" |
|
<< "\n\t item must be less than size()" |
|
<< "\n\t item: " << item |
|
<< "\n\t size(): " << size() |
|
<< "\n\t this: " << this |
|
); |
|
|
|
if (items[item].parent == item) |
|
{ |
|
return item; |
|
} |
|
else |
|
{ |
|
|
|
unsigned long x = item; |
|
do |
|
{ |
|
x = items[x].parent; |
|
} while (items[x].parent != x); |
|
|
|
|
|
const unsigned long root = x; |
|
x = item; |
|
while (items[x].parent != x) |
|
{ |
|
const unsigned long prev = x; |
|
x = items[x].parent; |
|
items[prev].parent = root; |
|
} |
|
|
|
return root; |
|
} |
|
} |
|
|
|
unsigned long merge_sets ( |
|
unsigned long a, |
|
unsigned long b |
|
) |
|
{ |
|
|
|
DLIB_ASSERT(a != b && |
|
a < size() && |
|
b < size() && |
|
find_set(a) == a && |
|
find_set(b) == b, |
|
"\t unsigned long disjoint_subsets::merge_sets(a,b)" |
|
<< "\n\t invalid arguments were given to this function" |
|
<< "\n\t a: " << a |
|
<< "\n\t b: " << b |
|
<< "\n\t size(): " << size() |
|
<< "\n\t find_set(a): " << find_set(a) |
|
<< "\n\t find_set(b): " << find_set(b) |
|
<< "\n\t this: " << this |
|
); |
|
|
|
if (items[a].rank > items[b].rank) |
|
{ |
|
items[b].parent = a; |
|
return a; |
|
} |
|
else |
|
{ |
|
items[a].parent = b; |
|
if (items[a].rank == items[b].rank) |
|
{ |
|
items[b].rank = items[b].rank + 1; |
|
} |
|
return b; |
|
} |
|
} |
|
|
|
private: |
|
|
|
|
|
|
|
|
|
|
|
|
|
struct data |
|
{ |
|
unsigned long rank; |
|
unsigned long parent; |
|
}; |
|
|
|
mutable std::vector<data> items; |
|
|
|
}; |
|
|
|
|
|
|
|
} |
|
|
|
#endif |
|
|