forked from ProAlgos/ProAlgos-Cpp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
disjoint_set.hpp
127 lines (96 loc) · 2.76 KB
/
disjoint_set.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/*
Disjoint-set
------------
A disjoint-set data structure (also called a union–find data structure or
merge–find set) keeps track of a set of elements partitioned into a number
of disjoint (non-overlapping) subsets.
*/
#ifndef DISJOINT_SET_HPP
#define DISJOINT_SET_HPP
#include <cstddef>
#include <vector>
struct Element {
int parent;
int rank;
};
/*
DisjointSet
-----------
Class implementing the disjoint-set data structure.
*/
class DisjointSet {
std::vector<Element> set;
public:
DisjointSet(size_t);
int find(int);
void join(int, int);
size_t size() const;
};
/*
Constructor
-----------
*/
DisjointSet::DisjointSet(size_t num_nodes) {
set.resize(num_nodes);
// initially all elements are parents of themselves, with rank 0
for (size_t element = 0; element < set.size(); element++) {
set[element].parent = element;
set[element].rank = 0;
}
}
/*
find
----
Returns the representative (root) element of the given element, while also
performing path compression - making the representative the parent of all
elements in the "path".
Time complexity
---------------
log*(N), where N is the number of elements in the disjoint-set.
Space complexity
----------------
O(1).
*/
int DisjointSet::find(int x) {
// recursively travel to the representative element while also performing
// path compression
if (set[x].parent != x)
set[x].parent = find(set[x].parent);
return set[x].parent;
}
/*
join
----
Joins the subsets to which the given elements belong to, depending on the
rank of their representative elements.
Time complexity
---------------
log*(N), where N is the number of elements in the disjoint-set.
Space complexity
----------------
O(1).
*/
void DisjointSet::join(int x, int y) {
// find the representatives (roots) of the given elements
int x_root = find(x);
int y_root = find(y);
if (x_root == y_root) // if x and y are already in the same set
return; // nothing to do
// otherwise, join them depending on their representative's rank
if (set[x_root].rank < set[y_root].rank) // if x's rank is less than y's
set[x_root].parent = y_root; // join x's root to y's
else { // if y's rank is less than (or equal to) x's
set[y_root].parent = x_root; // join y's root to x's
if (set[x_root].rank == set[y_root].rank) // if the ranks are equal
++set[x_root].rank; // increase the rank of x's representative
}
}
/*
size
----
Returns the number of elements in the set.
*/
size_t DisjointSet::size() const {
return set.size();
}
#endif // DISJOINT_SET_HPP