fibonacci_heap.hpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. // (C) Copyright Jeremy Siek 2004.
  2. // Distributed under the Boost Software License, Version 1.0. (See
  3. // accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. #ifndef BOOST_FIBONACCI_HEAP_HPP
  6. #define BOOST_FIBONACCI_HEAP_HPP
  7. #if defined(__sgi) && !defined(__GNUC__)
  8. # include <math.h>
  9. #else
  10. # include <boost/config/no_tr1/cmath.hpp>
  11. #endif
  12. #include <iosfwd>
  13. #include <vector>
  14. #include <functional>
  15. #include <boost/config.hpp>
  16. #include <boost/property_map/property_map.hpp>
  17. //
  18. // An adaptation of Knuth's Fibonacci heap implementation
  19. // in "The Stanford Graph Base", pages 475-482.
  20. //
  21. namespace boost {
  22. template <class T,
  23. class Compare = std::less<T>,
  24. class ID = identity_property_map>
  25. class fibonacci_heap
  26. {
  27. typedef typename boost::property_traits<ID>::value_type size_type;
  28. typedef T value_type;
  29. protected:
  30. typedef fibonacci_heap self;
  31. typedef std::vector<size_type> LinkVec;
  32. typedef typename LinkVec::iterator LinkIter;
  33. public:
  34. fibonacci_heap(size_type n,
  35. const Compare& cmp,
  36. const ID& id = identity_property_map())
  37. : _key(n), _left(n), _right(n), _p(n), _mark(n), _degree(n),
  38. _n(0), _root(n), _id(id), _compare(cmp), _child(n),
  39. #if defined(BOOST_MSVC) || defined(__ICL) // need a new macro?
  40. new_roots(size_type(log(float(n))) + 5) { }
  41. #else
  42. new_roots(size_type(std::log(float(n))) + 5) { }
  43. #endif
  44. // 33
  45. void push(const T& d) {
  46. ++_n;
  47. size_type v = get(_id, d);
  48. _key[v] = d;
  49. _p[v] = nil();
  50. _degree[v] = 0;
  51. _mark[v] = false;
  52. _child[v] = nil();
  53. if (_root == nil()) {
  54. _root = _left[v] = _right[v] = v;
  55. //std::cout << "root added" << std::endl;
  56. } else {
  57. size_type u = _left[_root];
  58. _left[v] = u;
  59. _right[v] = _root;
  60. _left[_root] = _right[u] = v;
  61. if (_compare(d, _key[_root]))
  62. _root = v;
  63. //std::cout << "non-root node added" << std::endl;
  64. }
  65. }
  66. T& top() { return _key[_root]; }
  67. const T& top() const { return _key[_root]; }
  68. // 38
  69. void pop() {
  70. --_n;
  71. int h = -1;
  72. size_type v, w;
  73. if (_root != nil()) {
  74. if (_degree[_root] == 0) {
  75. v = _right[_root];
  76. } else {
  77. w = _child[_root];
  78. v = _right[w];
  79. _right[w] = _right[_root];
  80. for (w = v; w != _right[_root]; w = _right[w])
  81. _p[w] = nil();
  82. }
  83. while (v != _root) {
  84. w = _right[v];
  85. add_tree_to_new_roots(v, new_roots.begin(), h);
  86. v = w;
  87. }
  88. rebuild_root_list(new_roots.begin(), h);
  89. }
  90. }
  91. // 39
  92. inline void add_tree_to_new_roots(size_type v,
  93. LinkIter new_roots,
  94. int& h)
  95. {
  96. int r;
  97. size_type u;
  98. r = _degree[v];
  99. while (1) {
  100. if (h < r) {
  101. do {
  102. ++h;
  103. new_roots[h] = (h == r ? v : nil());
  104. } while (h < r);
  105. break;
  106. }
  107. if (new_roots[r] == nil()) {
  108. new_roots[r] = v;
  109. break;
  110. }
  111. u = new_roots[r];
  112. new_roots[r] = nil();
  113. if (_compare(_key[u], _key[v])) {
  114. _degree[v] = r;
  115. _mark[v] = false;
  116. std::swap(u, v);
  117. }
  118. make_child(u, v, r);
  119. ++r;
  120. }
  121. _degree[v] = r;
  122. _mark[v] = false;
  123. }
  124. // 40
  125. void make_child(size_type u, size_type v, size_type r) {
  126. if (r == 0) {
  127. _child[v] = u;
  128. _left[u] = u;
  129. _right[u] = u;
  130. } else {
  131. size_type t = _child[v];
  132. _right[u] = _right[t];
  133. _left[u] = t;
  134. _right[t] = u;
  135. _left[_right[u]] = u;
  136. }
  137. _p[u] = v;
  138. }
  139. // 41
  140. inline void rebuild_root_list(LinkIter new_roots, int& h)
  141. {
  142. size_type u, v, w;
  143. if (h < 0)
  144. _root = nil();
  145. else {
  146. T d;
  147. u = v = new_roots[h];
  148. d = _key[u];
  149. _root = u;
  150. for (h--; h >= 0; --h)
  151. if (new_roots[h] != nil()) {
  152. w = new_roots[h];
  153. _left[w] = v;
  154. _right[v] = w;
  155. if (_compare(_key[w], d)) {
  156. _root = w;
  157. d = _key[w];
  158. }
  159. v = w;
  160. }
  161. _right[v] = u;
  162. _left[u] = v;
  163. }
  164. }
  165. // 34
  166. void update(const T& d) {
  167. size_type v = get(_id, d);
  168. assert(!_compare(_key[v], d));
  169. _key[v] = d;
  170. size_type p = _p[v];
  171. if (p == nil()) {
  172. if (_compare(d, _key[_root]))
  173. _root = v;
  174. } else if (_compare(d, _key[p]))
  175. while (1) {
  176. size_type r = _degree[p];
  177. if (r >= 2)
  178. remove_from_family(v, p);
  179. insert_into_forest(v, d);
  180. size_type pp = _p[p];
  181. if (pp == nil()) {
  182. --_degree[p];
  183. break;
  184. }
  185. if (_mark[p] == false) {
  186. _mark[p] = true;
  187. --_degree[p];
  188. break;
  189. } else
  190. --_degree[p];
  191. v = p;
  192. p = pp;
  193. }
  194. }
  195. inline size_type size() const { return _n; }
  196. inline bool empty() const { return _n == 0; }
  197. void print(std::ostream& os) {
  198. if (_root != nil()) {
  199. size_type i = _root;
  200. do {
  201. print_recur(i, os);
  202. os << std::endl;
  203. i = _right[i];
  204. } while (i != _root);
  205. }
  206. }
  207. protected:
  208. // 35
  209. inline void remove_from_family(size_type v, size_type p) {
  210. size_type u = _left[v];
  211. size_type w = _right[v];
  212. _right[u] = w;
  213. _left[w] = u;
  214. if (_child[p] == v)
  215. _child[p] = w;
  216. }
  217. // 36
  218. inline void insert_into_forest(size_type v, const T& d) {
  219. _p[v] = nil();
  220. size_type u = _left[_root];
  221. _left[v] = u;
  222. _right[v] = _root;
  223. _left[_root] = _right[u] = v;
  224. if (_compare(d, _key[_root]))
  225. _root = v;
  226. }
  227. void print_recur(size_type x, std::ostream& os) {
  228. if (x != nil()) {
  229. os << x;
  230. if (_degree[x] > 0) {
  231. os << "(";
  232. size_type i = _child[x];
  233. do {
  234. print_recur(i, os); os << " ";
  235. i = _right[i];
  236. } while (i != _child[x]);
  237. os << ")";
  238. }
  239. }
  240. }
  241. size_type nil() const { return _left.size(); }
  242. std::vector<T> _key;
  243. LinkVec _left, _right, _p;
  244. std::vector<bool> _mark;
  245. LinkVec _degree;
  246. size_type _n, _root;
  247. ID _id;
  248. Compare _compare;
  249. LinkVec _child;
  250. LinkVec new_roots;
  251. };
  252. } // namespace boost
  253. #endif // BOOST_FIBONACCI_HEAP_HPP