PhysicsBasedAnimationToolkit 0.0.10
Cross-platform C++20 library of algorithms and data structures commonly used in computer graphics research on physically-based simulation.
Loading...
Searching...
No Matches
DisjointSetUnionFind.h
1#ifndef PBAT_GRAPH_DISJOINTSETUNIONFIND_H
2#define PBAT_GRAPH_DISJOINTSETUNIONFIND_H
3
4#include "pbat/Aliases.h"
6
7#include <cassert>
8
9namespace pbat::graph {
10
19template <common::CIndex TIndex = Index>
20class DisjointSetUnionFind
21{
22 public:
23 using IndexType = TIndex;
24
25 DisjointSetUnionFind() = default;
30 DisjointSetUnionFind(IndexType n);
35 void Prepare(IndexType n);
54 IndexType Root(IndexType u) const;
60 IndexType Size(IndexType u) const;
65 IndexType NumVertices() const;
66
67 private:
68 Eigen::Vector<IndexType, Eigen::Dynamic> mParent;
69 Eigen::Vector<IndexType, Eigen::Dynamic> mRank;
70 Eigen::Vector<IndexType, Eigen::Dynamic> mSize;
71};
72
73template <common::CIndex TIndex>
74DisjointSetUnionFind<TIndex>::DisjointSetUnionFind(IndexType n) : DisjointSetUnionFind<TIndex>()
75{
76 Prepare(n);
77}
78
79template <common::CIndex TIndex>
81{
82 mParent = Eigen::Vector<IndexType, Eigen::Dynamic>::LinSpaced(n, IndexType(0), n - 1);
83 mRank.setZero(n);
84 mSize.setOnes(n);
85}
86
87template <common::CIndex TIndex>
89{
90 if (mParent[u] != u)
91 mParent[u] = Find(mParent[u]); // Path compression
92 return mParent[u];
93}
94
95template <common::CIndex TIndex>
97{
98 assert(u != v && "Cannot union the same vertex with itself.");
99 // Find roots of each node
100 IndexType const ru = Find(u);
101 IndexType const rv = Find(v);
102 // Make tree with smaller height a subtree of the other tree.
103 // This effectively minimizes the depth of the resulting merged tree.
104 if (mRank[ru] > mRank[rv])
105 {
106 mParent[rv] = ru;
107 mSize[ru] += mSize[rv];
108 mSize[rv] = IndexType(0);
109 }
110 else
111 {
112 mParent[ru] = rv;
113 mSize[rv] += mSize[ru];
114 mSize[ru] = IndexType(0);
115 }
116 // If both trees had the same depth, then
117 // making one tree a subtree of the other increased
118 // the depth of the merged tree by 1.
119 if (mRank[ru] == mRank[rv])
120 {
121 ++mRank[rv];
122 }
123 return (mParent[ru] == ru) ? ru : rv;
124}
125
126template <common::CIndex TIndex>
128{
129 while (mParent[u] != u)
130 u = mParent[u];
131 return u;
132}
133
134template <common::CIndex TIndex>
136{
137 return mSize[Root(u)];
138}
139
140template <common::CIndex TIndex>
142{
143 return static_cast<TIndex>(mSize.size());
144}
145
146} // namespace pbat::graph
147
148#endif // PBAT_GRAPH_DISJOINTSETUNIONFIND_H
IndexType Root(IndexType u) const
Find the root of the set containing vertex u without path compression.
Definition DisjointSetUnionFind.h:127
TIndex IndexType
Index type used in the disjoint set union-find structure.
Definition DisjointSetUnionFind.h:23
void Prepare(IndexType n)
Reserve memory for n vertices and reset the structure.
Definition DisjointSetUnionFind.h:80
IndexType Union(IndexType u, IndexType v)
Merge the sets containing vertices u and v
Definition DisjointSetUnionFind.h:96
IndexType Size(IndexType u) const
Find the size of the set containing vertex u
Definition DisjointSetUnionFind.h:135
IndexType NumVertices() const
Get the number of vertices in the disjoint set union-find structure.
Definition DisjointSetUnionFind.h:141
IndexType Find(IndexType u)
Find the root of the set containing vertex u
Definition DisjointSetUnionFind.h:88
Concepts for common types.
Definition Adjacency.h:24