disjoint_sets.hpp 6.4 KB

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