2 //=======================================================================
3 // Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
4 // Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
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 //=======================================================================
11 #ifndef BOOST_DISJOINT_SETS_HPP
12 #define BOOST_DISJOINT_SETS_HPP
15 #include <boost/graph/properties.hpp>
16 #include <boost/pending/detail/disjoint_sets.hpp>
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
);
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
);
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.
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
50 typedef disjoint_sets self
;
52 inline disjoint_sets() {}
54 inline disjoint_sets(RankPA r
, ParentPA p
)
55 : rank(r
), parent(p
) {}
57 inline disjoint_sets(const self
& c
)
58 : rank(c
.rank
), parent(c
.parent
) {}
60 // Make Set -- Create a singleton set containing vertex x
61 template <class Element
>
62 inline void make_set(Element x
)
65 typedef typename property_traits
<RankPA
>::value_type R
;
69 // Link - union the two sets represented by vertex x and y
70 template <class Element
>
71 inline void link(Element x
, Element y
)
73 detail::link_sets(parent
, rank
, x
, y
, rep
);
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
)
80 link(find_set(x
), find_set(y
));
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
)
88 return rep(parent
, x
);
91 template <class ElementIterator
>
92 inline std::size_t count_sets(ElementIterator first
, ElementIterator last
)
94 std::size_t count
= 0;
95 for ( ; first
!= last
; ++first
)
96 if (get(parent
, *first
) == *first
)
101 template <class ElementIterator
>
102 inline void normalize_sets(ElementIterator first
, ElementIterator last
)
104 for (; first
!= last
; ++first
)
105 detail::normalize_node(parent
, *first
);
108 template <class ElementIterator
>
109 inline void compress_sets(ElementIterator first
, ElementIterator last
)
111 for (; first
!= last
; ++first
)
112 detail::find_representative_with_full_compression(parent
, *first
);
123 template <class ID
= identity_property_map
,
124 class InverseID
= identity_property_map
,
125 class FindCompress
= find_with_full_path_compression
127 class disjoint_sets_with_storage
129 typedef typename property_traits
<ID
>::value_type Index
;
130 typedef std::vector
<Index
> ParentContainer
;
131 typedef std::vector
<unsigned char> RankContainer
;
133 typedef typename
ParentContainer::size_type size_type
;
135 disjoint_sets_with_storage(size_type n
= 0,
137 InverseID inv
= InverseID())
138 : id(id_
), id_to_vertex(inv
), rank(n
, 0), parent(n
)
140 for (Index i
= 0; i
< n
; ++i
)
143 // note this is not normally needed
144 template <class Element
>
146 make_set(Element x
) {
150 template <class Element
>
152 link(Element x
, Element y
)
155 detail::link_sets(&parent
[0], &rank
[0],
156 get(id
,x
), get(id
,y
), rep
);
158 template <class Element
>
160 union_set(Element x
, Element y
) {
161 Element rx
= find_set(x
);
162 Element ry
= find_set(y
);
165 template <class Element
>
166 inline Element
find_set(Element x
) {
167 return id_to_vertex
[rep(&parent
[0], get(id
,x
))];
170 template <class ElementIterator
>
171 inline std::size_t count_sets(ElementIterator first
, ElementIterator last
)
173 std::size_t count
= 0;
174 for ( ; first
!= last
; ++first
)
175 if (parent
[*first
] == *first
)
180 template <class ElementIterator
>
181 inline void normalize_sets(ElementIterator first
, ElementIterator last
)
183 for (; first
!= last
; ++first
)
184 detail::normalize_node(&parent
[0], *first
);
187 template <class ElementIterator
>
188 inline void compress_sets(ElementIterator first
, ElementIterator last
)
190 for (; first
!= last
; ++first
)
191 detail::find_representative_with_full_compression(&parent
[0],
195 const ParentContainer
& parents() { return parent
; }
199 template <class Element
>
201 extend_sets(Element x
, Element y
)
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
)
212 InverseID id_to_vertex
;
214 ParentContainer parent
;
220 #endif // BOOST_DISJOINT_SETS_HPP