1+ #pragma once
2+ #include < set>
3+ #include < memory>
4+ #include < unordered_map>
5+ #include < initializer_list>
6+ #include < stdexcept>
7+ #include < assert.h>
8+ namespace colinli {
9+ namespace algon {
10+
11+ template <typename T>
12+ using uPtr = std::shared_ptr<T>;
13+ template <typename T>
14+ using Set = std::set < T > ;
15+ template <typename K, typename V>
16+ using HashMap = std::unordered_map < K, V > ;
17+
18+ template <typename TKey>
19+ class DisjointSets
20+ {
21+ private:
22+ Set<TKey> keys_;
23+ HashMap<TKey, TKey> parent_;
24+ HashMap<TKey, int > rank_;
25+ public:
26+ DisjointSets (){}
27+ DisjointSets (std::initializer_list<TKey> keys):
28+ keys_ (keys)
29+ {
30+ for (auto k : keys_)
31+ {
32+ parent_[k] = k;
33+ rank_[k] = 1 ;
34+ }
35+ }
36+ // / <summary>
37+ // / Unions two elements
38+ // / </summary>
39+ void Union (TKey x, TKey y)
40+ {
41+ linkRoot (*FindSet (x), *FindSet (y));
42+ }
43+
44+ // / <summary>
45+ // / Unions more than two elements
46+ // / </summary>
47+ template <typename TKey, typename ... TRest >
48+ void Union (TKey x, TKey y, TRest... rest)
49+ {
50+ Union (x, y);
51+ Union (y, rest...);
52+ }
53+
54+ bool Contains (TKey x) const
55+ {
56+ return keys_.count (x) != 0 ;
57+ }
58+
59+ // / <summary>
60+ // / Finds the set representative (root) for given element x
61+ // / </summary>
62+ // / <param name="x">input element</param>
63+ // / <returns>the pointer to root of the set to which x belongs</returns>
64+ TKey* FindSet (TKey x)
65+ {
66+ if (parent_.count (x) == 0 )
67+ {
68+ return nullptr ;
69+ }
70+ while (parent_[x] != x)
71+ {
72+ x = *FindSet (parent_[x]);
73+ }
74+ return &x;
75+ }
76+ // / <summary>
77+ // / Test connectivity of two elements
78+ // / </summary>
79+ // / <returns>true if the two elements are connected</returns>
80+ bool Connected (TKey x, TKey y)
81+ {
82+ if (parent_.count (x) == 0 || parent_.count (y) == 0 )
83+ {
84+ return false ;
85+ }
86+ return FindSet (x) == FindSet (y);
87+ }
88+
89+ void Add (TKey x)
90+ {
91+ keys_.insert (x);
92+ parent_[x] = x;
93+ rank_[x] = 1 ;
94+ }
95+
96+ private:
97+ // x and y are two roots to be linked
98+ void linkRoot (TKey x, TKey y)
99+ {
100+ assert (parent_[x] == x && parent_[y] == y);
101+ if (x == y)
102+ {
103+ return ;
104+ }
105+ if (rank_[x] < rank_[y])
106+ {
107+ parent_[x] = y;
108+ }
109+ else
110+ {
111+ parent_[y] = x;
112+ }
113+ if (rank_[x] == rank_[y])
114+ {
115+ ++rank_[y];
116+ }
117+ }
118+ };
119+
120+ }// end of algon ns
121+ }// end of colinli ns
0 commit comments