Skip to content

Commit 31ff659

Browse files
author
Colin Lin
committed
Add DisjointSet
1 parent e7aa4e8 commit 31ff659

File tree

7 files changed

+177
-1
lines changed

7 files changed

+177
-1
lines changed

Algon/Algon.vcxproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
</Link>
6565
</ItemDefinitionGroup>
6666
<ItemGroup>
67+
<ClInclude Include="dstruct\DisjointSet.h" />
6768
<ClInclude Include="dstruct\SkipList.h" />
6869
</ItemGroup>
6970
<ItemGroup>

Algon/Algon.vcxproj.filters

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
<ClInclude Include="dstruct\SkipList.h">
1919
<Filter>Header Files</Filter>
2020
</ClInclude>
21+
<ClInclude Include="dstruct\DisjointSet.h">
22+
<Filter>Header Files</Filter>
23+
</ClInclude>
2124
</ItemGroup>
2225
<ItemGroup>
2326
<ClCompile Include="Example.cpp">

Algon/dstruct/DisjointSet.h

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
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

tests/DisjointSetTest.cpp

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#include "stdafx.h"
2+
#include "CppUnitTest.h"
3+
4+
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
5+
using namespace colinli::algon;
6+
namespace tests
7+
{
8+
TEST_CLASS(DisjointSetTest)
9+
{
10+
public:
11+
DisjointSets<int> iset;
12+
TEST_METHOD_INITIALIZE(InitializeSet)
13+
{
14+
for (int i = 0; i < 10; i++)
15+
{
16+
iset.Add(i);
17+
}
18+
}
19+
20+
TEST_METHOD(TestContains)
21+
{
22+
Assert::IsTrue(iset.Contains(2));
23+
}
24+
TEST_METHOD(TestUnion)
25+
{
26+
iset.Union(1, 2);
27+
iset.Union(2, 5);
28+
iset.Union(3, 5);
29+
Assert::IsTrue(iset.Connected(1, 2));
30+
Assert::IsTrue(iset.Connected(1, 5));
31+
Assert::IsTrue(iset.Connected(1, 3));
32+
Assert::IsTrue(iset.Connected(2, 3));
33+
}
34+
35+
TEST_METHOD(TestMultiUnion)
36+
{
37+
iset.Union(1, 2, 3, 4);
38+
iset.Union(2, 7);
39+
Assert::IsTrue(iset.Connected(1, 7));
40+
Assert::IsTrue(iset.Connected(4, 7));
41+
Assert::IsTrue(iset.Connected(4, 3));
42+
}
43+
44+
45+
};
46+
}

tests/stdafx.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,5 @@
1111
#include "CppUnitTest.h"
1212
#include <string>
1313
// TODO: reference additional headers your program requires here
14-
#include "../Algon/dstruct/SkipList.h"
14+
#include "../Algon/dstruct/SkipList.h"
15+
#include "../Algon/dstruct/DisjointSet.h"

tests/tests.vcxproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@
8686
<ClInclude Include="targetver.h" />
8787
</ItemGroup>
8888
<ItemGroup>
89+
<ClCompile Include="DisjointSetTest.cpp" />
8990
<ClCompile Include="stdafx.cpp">
9091
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
9192
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>

tests/tests.vcxproj.filters

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,8 @@
2929
<ClCompile Include="SkiplistTests.cpp">
3030
<Filter>Source Files</Filter>
3131
</ClCompile>
32+
<ClCompile Include="DisjointSetTest.cpp">
33+
<Filter>Source Files</Filter>
34+
</ClCompile>
3235
</ItemGroup>
3336
</Project>

0 commit comments

Comments
 (0)