]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/pending/disjoint_sets.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / pending / disjoint_sets.hpp
1 //
2 //=======================================================================
3 // Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
4 // Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
5 //
6 // Distributed under the Boost Software License, Version 1.0. (See
7 // accompanying file LICENSE_1_0.txt or copy at
8 // http://www.boost.org/LICENSE_1_0.txt)
9 //=======================================================================
10 //
11 #ifndef BOOST_DISJOINT_SETS_HPP
12 #define BOOST_DISJOINT_SETS_HPP
13
14 #include <vector>
15 #include <boost/graph/properties.hpp>
16 #include <boost/pending/detail/disjoint_sets.hpp>
17
18 namespace boost {
19
20 struct find_with_path_halving {
21 template <class ParentPA, class Vertex>
22 Vertex operator()(ParentPA p, Vertex v) {
23 return detail::find_representative_with_path_halving(p, v);
24 }
25 };
26
27 struct find_with_full_path_compression {
28 template <class ParentPA, class Vertex>
29 Vertex operator()(ParentPA p, Vertex v){
30 return detail::find_representative_with_full_compression(p, v);
31 }
32 };
33
34 // This is a generalized functor to provide disjoint sets operations
35 // with "union by rank" and "path compression". A disjoint-set data
36 // structure maintains a collection S={S1, S2, ..., Sk} of disjoint
37 // sets. Each set is identified by a representative, which is some
38 // member of of the set. Sets are represented by rooted trees. Two
39 // heuristics: "union by rank" and "path compression" are used to
40 // speed up the operations.
41
42 // Disjoint Set requires two vertex properties for internal use. A
43 // RankPA and a ParentPA. The RankPA must map Vertex to some Integral type
44 // (preferably the size_type associated with Vertex). The ParentPA
45 // must map Vertex to Vertex.
46 template <class RankPA, class ParentPA,
47 class FindCompress = find_with_full_path_compression
48 >
49 class disjoint_sets {
50 typedef disjoint_sets self;
51
52 inline disjoint_sets() {}
53 public:
54 inline disjoint_sets(RankPA r, ParentPA p)
55 : rank(r), parent(p) {}
56
57 inline disjoint_sets(const self& c)
58 : rank(c.rank), parent(c.parent) {}
59
60 // Make Set -- Create a singleton set containing vertex x
61 template <class Element>
62 inline void make_set(Element x)
63 {
64 put(parent, x, x);
65 typedef typename property_traits<RankPA>::value_type R;
66 put(rank, x, R());
67 }
68
69 // Link - union the two sets represented by vertex x and y
70 template <class Element>
71 inline void link(Element x, Element y)
72 {
73 detail::link_sets(parent, rank, x, y, rep);
74 }
75
76 // Union-Set - union the two sets containing vertex x and y
77 template <class Element>
78 inline void union_set(Element x, Element y)
79 {
80 link(find_set(x), find_set(y));
81 }
82
83 // Find-Set - returns the Element representative of the set
84 // containing Element x and applies path compression.
85 template <class Element>
86 inline Element find_set(Element x)
87 {
88 return rep(parent, x);
89 }
90
91 template <class ElementIterator>
92 inline std::size_t count_sets(ElementIterator first, ElementIterator last)
93 {
94 std::size_t count = 0;
95 for ( ; first != last; ++first)
96 if (get(parent, *first) == *first)
97 ++count;
98 return count;
99 }
100
101 template <class ElementIterator>
102 inline void normalize_sets(ElementIterator first, ElementIterator last)
103 {
104 for (; first != last; ++first)
105 detail::normalize_node(parent, *first);
106 }
107
108 template <class ElementIterator>
109 inline void compress_sets(ElementIterator first, ElementIterator last)
110 {
111 for (; first != last; ++first)
112 detail::find_representative_with_full_compression(parent, *first);
113 }
114 protected:
115 RankPA rank;
116 ParentPA parent;
117 FindCompress rep;
118 };
119
120
121
122
123 template <class ID = identity_property_map,
124 class InverseID = identity_property_map,
125 class FindCompress = find_with_full_path_compression
126 >
127 class disjoint_sets_with_storage
128 {
129 typedef typename property_traits<ID>::value_type Index;
130 typedef std::vector<Index> ParentContainer;
131 typedef std::vector<unsigned char> RankContainer;
132 public:
133 typedef typename ParentContainer::size_type size_type;
134
135 disjoint_sets_with_storage(size_type n = 0,
136 ID id_ = ID(),
137 InverseID inv = InverseID())
138 : id(id_), id_to_vertex(inv), rank(n, 0), parent(n)
139 {
140 for (Index i = 0; i < n; ++i)
141 parent[i] = i;
142 }
143 // note this is not normally needed
144 template <class Element>
145 inline void
146 make_set(Element x) {
147 parent[x] = x;
148 rank[x] = 0;
149 }
150 template <class Element>
151 inline void
152 link(Element x, Element y)
153 {
154 extend_sets(x,y);
155 detail::link_sets(&parent[0], &rank[0],
156 get(id,x), get(id,y), rep);
157 }
158 template <class Element>
159 inline void
160 union_set(Element x, Element y) {
161 Element rx = find_set(x);
162 Element ry = find_set(y);
163 link(rx, ry);
164 }
165 template <class Element>
166 inline Element find_set(Element x) {
167 return id_to_vertex[rep(&parent[0], get(id,x))];
168 }
169
170 template <class ElementIterator>
171 inline std::size_t count_sets(ElementIterator first, ElementIterator last)
172 {
173 std::size_t count = 0;
174 for ( ; first != last; ++first)
175 if (parent[*first] == *first)
176 ++count;
177 return count;
178 }
179
180 template <class ElementIterator>
181 inline void normalize_sets(ElementIterator first, ElementIterator last)
182 {
183 for (; first != last; ++first)
184 detail::normalize_node(&parent[0], *first);
185 }
186
187 template <class ElementIterator>
188 inline void compress_sets(ElementIterator first, ElementIterator last)
189 {
190 for (; first != last; ++first)
191 detail::find_representative_with_full_compression(&parent[0],
192 *first);
193 }
194
195 const ParentContainer& parents() { return parent; }
196
197 protected:
198
199 template <class Element>
200 inline void
201 extend_sets(Element x, Element y)
202 {
203 Index needed = get(id,x) > get(id,y) ? get(id,x) + 1 : get(id,y) + 1;
204 if (needed > parent.size()) {
205 rank.insert(rank.end(), needed - rank.size(), 0);
206 for (Index k = parent.size(); k < needed; ++k)
207 parent.push_back(k);
208 }
209 }
210
211 ID id;
212 InverseID id_to_vertex;
213 RankContainer rank;
214 ParentContainer parent;
215 FindCompress rep;
216 };
217
218 } // namespace boost
219
220 #endif // BOOST_DISJOINT_SETS_HPP