-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDisjointSet.cpp
More file actions
124 lines (103 loc) · 3.93 KB
/
DisjointSet.cpp
File metadata and controls
124 lines (103 loc) · 3.93 KB
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
#include <stdexcept>
#include "DisjointSet.hpp"
#include "DisjointSetElement.hpp"
//==============================================================================
template <class T> DisjointSet<T>::DisjointSet()
{
}
//==============================================================================
template <class T>
DisjointSet<T>::DisjointSet(const DisjointSet<T>& disjoint_set)
{
*this = disjoint_set;
}
//==============================================================================
template <class T> DisjointSet<T>::~DisjointSet()
{
}
//==============================================================================
template <class T> void DisjointSet<T>::makeSet(T* element)
{
// Make sure we're not already tracking this element.
if (elements_map.find(element) != elements_map.end())
{
throw std::runtime_error("Element is already in at least one set");
}
// Keep track of this new element. We can't have the DisjointSetElement set
// itself as its own parent here, because at the DisjointSetElement always
// has the same memory address here.
elements_map[element] = DisjointSetElement<T>(element);
// Set the new element as its own parent after it's been copied into the
// map, ensuring it has the right parent pointer.
elements_map[element].setParent(&elements_map[element]);
}
//==============================================================================
template <class T> void DisjointSet<T>::unionSets(T* element1, T* element2)
{
T* rep_element1 = find(element1);
T* rep_element2 = find(element2);
// These elements will have the same representative if they are already in
// the same set.
if (rep_element1 == rep_element2)
{
return;
}
elements_map[rep_element1].setParent(&elements_map[rep_element2]);
}
//==============================================================================
template <class T> T* DisjointSet<T>::find(T* element)
{
// Why is "typename" needed here?
typename std::map<T*, DisjointSetElement<T> >::iterator dj_element =
elements_map.find(element);
if (dj_element == elements_map.end())
{
throw std::runtime_error("Element is not in any set");
// We have nothing useful to return here.
return 0;
}
// Find the representative. This is the part that scales poorly without
// path compression.
DisjointSetElement<T>* representative = &dj_element->second;
while (representative->getParent() != representative)
{
representative = representative->getParent();
}
return representative->getElement();
}
//==============================================================================
template <class T> bool DisjointSet<T>::isRepresentative(T* element)
{
// Finds on the representative element of a set return the representative.
return element == find(element);
}
//==============================================================================
template <class T> void DisjointSet<T>::getElementsMap(
std::map<T*, DisjointSetElement<T> >& elements_map) const
{
elements_map = this->elements_map;
}
//==============================================================================
template <class T>
DisjointSet<T>& DisjointSet<T>::operator=(const DisjointSet<T>& disjoint_set)
{
// Don't do anything if we're assigning to ourselves
if (this != &disjoint_set)
{
disjoint_set.getElementsMap(this->elements_map);
}
return *this;
}
template class DisjointSet<char>;
template class DisjointSet<double>;
template class DisjointSet<float>;
template class DisjointSet<int>;
template class DisjointSet<long>;
template class DisjointSet<long double>;
template class DisjointSet<long long>;
template class DisjointSet<short>;
template class DisjointSet<unsigned char>;
template class DisjointSet<unsigned int>;
template class DisjointSet<unsigned long>;
template class DisjointSet<unsigned long long>;
template class DisjointSet<unsigned short>;