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