disjoint_sets.hpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  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. #include <vector>
  14. #include <boost/graph/properties.hpp>
  15. #include <boost/pending/detail/disjoint_sets.hpp>
  16. namespace boost {
  17. struct find_with_path_halving {
  18. template <class ParentPA, class Vertex>
  19. Vertex operator()(ParentPA p, Vertex v) {
  20. return detail::find_representative_with_path_halving(p, v);
  21. }
  22. };
  23. struct find_with_full_path_compression {
  24. template <class ParentPA, class Vertex>
  25. Vertex operator()(ParentPA p, Vertex v){
  26. return detail::find_representative_with_full_compression(p, v);
  27. }
  28. };
  29. // This is a generalized functor to provide disjoint sets operations
  30. // with "union by rank" and "path compression". A disjoint-set data
  31. // structure maintains a collection S={S1, S2, ..., Sk} of disjoint
  32. // sets. Each set is identified by a representative, which is some
  33. // member of of the set. Sets are represented by rooted trees. Two
  34. // heuristics: "union by rank" and "path compression" are used to
  35. // speed up the operations.
  36. // Disjoint Set requires two vertex properties for internal use. A
  37. // RankPA and a ParentPA. The RankPA must map Vertex to some Integral type
  38. // (preferably the size_type associated with Vertex). The ParentPA
  39. // must map Vertex to Vertex.
  40. template <class RankPA, class ParentPA,
  41. class FindCompress = find_with_full_path_compression
  42. >
  43. class disjoint_sets {
  44. typedef disjoint_sets self;
  45. inline disjoint_sets() {}
  46. public:
  47. inline disjoint_sets(RankPA r, ParentPA p)
  48. : rank(r), parent(p) {}
  49. inline disjoint_sets(const self& c)
  50. : rank(c.rank), parent(c.parent) {}
  51. // Make Set -- Create a singleton set containing vertex x
  52. template <class Element>
  53. inline void make_set(Element x)
  54. {
  55. put(parent, x, x);
  56. typedef typename property_traits<RankPA>::value_type R;
  57. put(rank, x, R());
  58. }
  59. // Link - union the two sets represented by vertex x and y
  60. template <class Element>
  61. inline void link(Element x, Element y)
  62. {
  63. detail::link_sets(parent, rank, x, y, rep);
  64. }
  65. // Union-Set - union the two sets containing vertex x and y
  66. template <class Element>
  67. inline void union_set(Element x, Element y)
  68. {
  69. link(find_set(x), find_set(y));
  70. }
  71. // Find-Set - returns the Element representative of the set
  72. // containing Element x and applies path compression.
  73. template <class Element>
  74. inline Element find_set(Element x)
  75. {
  76. return rep(parent, x);
  77. }
  78. template <class ElementIterator>
  79. inline std::size_t count_sets(ElementIterator first, ElementIterator last)
  80. {
  81. std::size_t count = 0;
  82. for ( ; first != last; ++first)
  83. if (get(parent, *first) == *first)
  84. ++count;
  85. return count;
  86. }
  87. template <class ElementIterator>
  88. inline void normalize_sets(ElementIterator first, ElementIterator last)
  89. {
  90. for (; first != last; ++first)
  91. detail::normalize_node(parent, *first);
  92. }
  93. template <class ElementIterator>
  94. inline void compress_sets(ElementIterator first, ElementIterator last)
  95. {
  96. for (; first != last; ++first)
  97. detail::find_representative_with_full_compression(parent, *first);
  98. }
  99. protected:
  100. RankPA rank;
  101. ParentPA parent;
  102. FindCompress rep;
  103. };
  104. template <class ID = identity_property_map,
  105. class InverseID = identity_property_map,
  106. class FindCompress = find_with_full_path_compression
  107. >
  108. class disjoint_sets_with_storage
  109. {
  110. typedef typename property_traits<ID>::value_type Index;
  111. typedef std::vector<Index> ParentContainer;
  112. typedef std::vector<unsigned char> RankContainer;
  113. public:
  114. typedef typename ParentContainer::size_type size_type;
  115. disjoint_sets_with_storage(size_type n = 0,
  116. ID id_ = ID(),
  117. InverseID inv = InverseID())
  118. : id(id_), id_to_vertex(inv), rank(n, 0), parent(n)
  119. {
  120. for (Index i = 0; i < n; ++i)
  121. parent[i] = i;
  122. }
  123. // note this is not normally needed
  124. template <class Element>
  125. inline void
  126. make_set(Element x) {
  127. parent[x] = x;
  128. rank[x] = 0;
  129. }
  130. template <class Element>
  131. inline void
  132. link(Element x, Element y)
  133. {
  134. extend_sets(x,y);
  135. detail::link_sets(&parent[0], &rank[0],
  136. get(id,x), get(id,y), rep);
  137. }
  138. template <class Element>
  139. inline void
  140. union_set(Element x, Element y) {
  141. Element rx = find_set(x);
  142. Element ry = find_set(y);
  143. link(rx, ry);
  144. }
  145. template <class Element>
  146. inline Element find_set(Element x) {
  147. return id_to_vertex[rep(&parent[0], get(id,x))];
  148. }
  149. template <class ElementIterator>
  150. inline std::size_t count_sets(ElementIterator first, ElementIterator last)
  151. {
  152. std::size_t count = 0;
  153. for ( ; first != last; ++first)
  154. if (parent[*first] == *first)
  155. ++count;
  156. return count;
  157. }
  158. template <class ElementIterator>
  159. inline void normalize_sets(ElementIterator first, ElementIterator last)
  160. {
  161. for (; first != last; ++first)
  162. detail::normalize_node(&parent[0], *first);
  163. }
  164. template <class ElementIterator>
  165. inline void compress_sets(ElementIterator first, ElementIterator last)
  166. {
  167. for (; first != last; ++first)
  168. detail::find_representative_with_full_compression(&parent[0],
  169. *first);
  170. }
  171. const ParentContainer& parents() { return parent; }
  172. protected:
  173. template <class Element>
  174. inline void
  175. extend_sets(Element x, Element y)
  176. {
  177. Index needed = get(id,x) > get(id,y) ? get(id,x) + 1 : get(id,y) + 1;
  178. if (needed > parent.size()) {
  179. rank.insert(rank.end(), needed - rank.size(), 0);
  180. for (Index k = parent.size(); k < needed; ++k)
  181. parent.push_back(k);
  182. }
  183. }
  184. ID id;
  185. InverseID id_to_vertex;
  186. RankContainer rank;
  187. ParentContainer parent;
  188. FindCompress rep;
  189. };
  190. } // namespace boost
  191. #endif // BOOST_DISJOINT_SETS_HPP