// (C) Copyright Jeremy Siek 2004. // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_FIBONACCI_HEAP_HPP #define BOOST_FIBONACCI_HEAP_HPP #if defined(__sgi) && !defined(__GNUC__) #include #else #include #endif #include #include #include #include #include // // An adaptation of Knuth's Fibonacci heap implementation // in "The Stanford Graph Base", pages 475-482. // namespace boost { template < class T, class Compare = std::less< T >, class ID = identity_property_map > class fibonacci_heap { typedef typename boost::property_traits< ID >::value_type size_type; typedef T value_type; protected: typedef fibonacci_heap self; typedef std::vector< size_type > LinkVec; typedef typename LinkVec::iterator LinkIter; public: fibonacci_heap( size_type n, const Compare& cmp, const ID& id = identity_property_map()) : _key(n) , _left(n) , _right(n) , _p(n) , _mark(n) , _degree(n) , _n(0) , _root(n) , _id(id) , _compare(cmp) , _child(n) , #if defined(BOOST_MSVC) || defined(__ICL) // need a new macro? new_roots(size_type(log(float(n))) + 5) { } #else new_roots(size_type(std::log(float(n))) + 5) { } #endif // 33 void push(const T& d) { ++_n; size_type v = get(_id, d); _key[v] = d; _p[v] = nil(); _degree[v] = 0; _mark[v] = false; _child[v] = nil(); if (_root == nil()) { _root = _left[v] = _right[v] = v; // std::cout << "root added" << std::endl; } else { size_type u = _left[_root]; _left[v] = u; _right[v] = _root; _left[_root] = _right[u] = v; if (_compare(d, _key[_root])) _root = v; // std::cout << "non-root node added" << std::endl; } } T& top() { return _key[_root]; } const T& top() const { return _key[_root]; } // 38 void pop() { --_n; int h = -1; size_type v, w; if (_root != nil()) { if (_degree[_root] == 0) { v = _right[_root]; } else { w = _child[_root]; v = _right[w]; _right[w] = _right[_root]; for (w = v; w != _right[_root]; w = _right[w]) _p[w] = nil(); } while (v != _root) { w = _right[v]; add_tree_to_new_roots(v, new_roots.begin(), h); v = w; } rebuild_root_list(new_roots.begin(), h); } } // 39 inline void add_tree_to_new_roots(size_type v, LinkIter new_roots, int& h) { int r; size_type u; r = _degree[v]; while (1) { if (h < r) { do { ++h; new_roots[h] = (h == r ? v : nil()); } while (h < r); break; } if (new_roots[r] == nil()) { new_roots[r] = v; break; } u = new_roots[r]; new_roots[r] = nil(); if (_compare(_key[u], _key[v])) { _degree[v] = r; _mark[v] = false; std::swap(u, v); } make_child(u, v, r); ++r; } _degree[v] = r; _mark[v] = false; } // 40 void make_child(size_type u, size_type v, size_type r) { if (r == 0) { _child[v] = u; _left[u] = u; _right[u] = u; } else { size_type t = _child[v]; _right[u] = _right[t]; _left[u] = t; _right[t] = u; _left[_right[u]] = u; } _p[u] = v; } // 41 inline void rebuild_root_list(LinkIter new_roots, int& h) { size_type u, v, w; if (h < 0) _root = nil(); else { T d; u = v = new_roots[h]; d = _key[u]; _root = u; for (h--; h >= 0; --h) if (new_roots[h] != nil()) { w = new_roots[h]; _left[w] = v; _right[v] = w; if (_compare(_key[w], d)) { _root = w; d = _key[w]; } v = w; } _right[v] = u; _left[u] = v; } } // 34 void update(const T& d) { size_type v = get(_id, d); assert(!_compare(_key[v], d)); _key[v] = d; size_type p = _p[v]; if (p == nil()) { if (_compare(d, _key[_root])) _root = v; } else if (_compare(d, _key[p])) while (1) { size_type r = _degree[p]; if (r >= 2) remove_from_family(v, p); insert_into_forest(v, d); size_type pp = _p[p]; if (pp == nil()) { --_degree[p]; break; } if (_mark[p] == false) { _mark[p] = true; --_degree[p]; break; } else --_degree[p]; v = p; p = pp; } } inline size_type size() const { return _n; } inline bool empty() const { return _n == 0; } void print(std::ostream& os) { if (_root != nil()) { size_type i = _root; do { print_recur(i, os); os << std::endl; i = _right[i]; } while (i != _root); } } protected: // 35 inline void remove_from_family(size_type v, size_type p) { size_type u = _left[v]; size_type w = _right[v]; _right[u] = w; _left[w] = u; if (_child[p] == v) _child[p] = w; } // 36 inline void insert_into_forest(size_type v, const T& d) { _p[v] = nil(); size_type u = _left[_root]; _left[v] = u; _right[v] = _root; _left[_root] = _right[u] = v; if (_compare(d, _key[_root])) _root = v; } void print_recur(size_type x, std::ostream& os) { if (x != nil()) { os << x; if (_degree[x] > 0) { os << "("; size_type i = _child[x]; do { print_recur(i, os); os << " "; i = _right[i]; } while (i != _child[x]); os << ")"; } } } size_type nil() const { return _left.size(); } std::vector< T > _key; LinkVec _left, _right, _p; std::vector< bool > _mark; LinkVec _degree; size_type _n, _root; ID _id; Compare _compare; LinkVec _child; LinkVec new_roots; }; } // namespace boost #endif // BOOST_FIBONACCI_HEAP_HPP