Clustering
C++20 header-only: DBSCAN, HDBSCAN, k-means.
Loading...
Searching...
No Matches
dsu.h
Go to the documentation of this file.
1#pragma once
2
3#include <cassert>
4#include <cstddef>
5#include <cstdint>
6#include <type_traits>
7#include <vector>
8
9namespace clustering {
10
22template <class Idx = std::uint32_t> class UnionFind {
23public:
24 static_assert(std::is_unsigned_v<Idx>, "UnionFind Idx must be an unsigned integer type");
25
31 explicit UnionFind(std::size_t n) : m_parent(n), m_rank(n, 0), m_size(n, 1), m_components(n) {
32 for (std::size_t i = 0; i < n; ++i) {
33 m_parent[i] = static_cast<Idx>(i);
34 }
35 }
36
47 Idx find(Idx x) noexcept {
48 assert(static_cast<std::size_t>(x) < m_parent.size() && "UnionFind::find index out of range");
49 Idx root = x;
50 while (m_parent[root] != root) {
51 root = m_parent[root];
52 }
53 Idx node = x;
54 while (m_parent[node] != root) {
55 const Idx next = m_parent[node];
56 m_parent[node] = root;
57 node = next;
58 }
59 return root;
60 }
61
73 bool unite(Idx a, Idx b) noexcept {
74 Idx ra = find(a);
75 Idx rb = find(b);
76 if (ra == rb) {
77 return false;
78 }
79 if (m_rank[ra] < m_rank[rb]) {
80 m_parent[ra] = rb;
81 m_size[rb] += m_size[ra];
82 } else if (m_rank[ra] > m_rank[rb]) {
83 m_parent[rb] = ra;
84 m_size[ra] += m_size[rb];
85 } else {
86 m_parent[rb] = ra;
87 m_size[ra] += m_size[rb];
88 ++m_rank[ra];
89 }
90 --m_components;
91 return true;
92 }
93
103 bool sameComponent(Idx a, Idx b) noexcept { return find(a) == find(b); }
104
112 [[nodiscard]] std::size_t countComponents() const noexcept { return m_components; }
113
119 [[nodiscard]] std::size_t size() const noexcept { return m_parent.size(); }
120
132 [[nodiscard]] std::size_t componentSize(Idx root) const noexcept {
133 assert(static_cast<std::size_t>(root) < m_parent.size() &&
134 "UnionFind::componentSize index out of range");
135 return m_size[root];
136 }
137
138private:
139 std::vector<Idx> m_parent;
140 std::vector<std::uint8_t> m_rank;
141 std::vector<std::size_t> m_size;
142 std::size_t m_components;
143};
144
145} // namespace clustering
Idx find(Idx x) noexcept
Root of the component containing x, with path compression applied.
Definition dsu.h:47
std::size_t size() const noexcept
Total number of elements under management (fixed at construction).
Definition dsu.h:119
bool unite(Idx a, Idx b) noexcept
Merge the components containing a and b.
Definition dsu.h:73
std::size_t componentSize(Idx root) const noexcept
Population of the component whose root is root.
Definition dsu.h:132
UnionFind(std::size_t n)
Construct n singleton components numbered [0, n).
Definition dsu.h:31
bool sameComponent(Idx a, Idx b) noexcept
Whether a and b share a component.
Definition dsu.h:103
std::size_t countComponents() const noexcept
Current number of distinct components.
Definition dsu.h:112