blob: 494f22830010324d27c233b1ae882ac473555261 [file] [log] [blame]
[library Boost.Heap
[quickbook 1.4]
[authors [Blechmann, Tim]]
[copyright 2010-2011 Tim Blechmann]
[category algorithms]
[purpose
heap data structures
]
[id heap]
[dirname heap]
[license
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])
]
]
[c++]
[/ Links ]
[def _heap_ [^boost.heap]]
[/ unspecified stuff ]
[def __unspecified_int__ /unspecified-int-type/]
[def __unspecified__ /unspecified/]
[def __unspecified_bool__ /unspecified-bool-type/]
[section Introduction & Motivation]
_heap_ is an implementation of priority queues. Priority queues are queue data structures, that order their elements by
a priority. The STL provides a single template class =std::priority_queue=, which only provides a limited functionality.
To overcome these limitations, _heap_ implements [link heap.data_structures data structures] with more functionality and
different performance characteristics. Especially, it deals with additional aspects:
* *Mutability*: The priority of heap elements can be modified.
* *Iterators*: Heaps provide iterators to iterate all elements.
* *Mergable*: While all heaps can be merged, some can be merged efficiently.
* *Stability*: Heaps can be configured to be stable sorted.
* *Comparison*: Heaps can be compared for equivalence.
[endsect]
[section:concepts Concepts & Interface]
[section:basic Basic Priority Queue Interface]
Priority queues are queues of objects, that are ordered by their priority. They support the operations of adding nodes to
the data structure, accessing the top element (the element with the highest priority), and removing the top element.
[note _heap_ implements priority queues as max-heaps to be consistent with the STL heap functions. This is in contrast to
the typical textbook design, which uses min-heaps.]
[h5 Synopsis]
template <typename T, class ...Options>
class priority_queue
{
// types
typedef T value_type;
typedef ``/unspecified/`` size_type;
typedef ``/unspecified/`` difference_type;
typedef ``/unspecified/`` allocator_type;
typedef ``/unspecified/`` value_compare;
typedef ``/unspecified/`` reference;
typedef ``/unspecified/`` const_reference;
typedef ``/unspecified/`` pointer;
typedef ``/unspecified/`` const_pointer;
// construct/copy/destruct
explicit priority_queue(value_compare const & = value_compare());
priority_queue(priority_queue const &);
priority_queue& operator=(priority_queue const &);
priority_queue(priority_queue &&); // move semantics (C++11 only)
priority_queue& operator=(priority_queue &&); // move semantics (C++11 only)
// public member functions
``/unspecified/`` push(const_reference); // push new element to heap
template<class... Args> void emplace(Args &&...); // push new element to heap, C++11 only
const_reference top() const; // return top element
void pop(); // remove top element
void clear(); // clear heap
size_type size() const; // number of elements
bool empty() const; // priority queue is empty
allocator_type get_allocator(void) const; // return allocator
size_type max_size(void) const; // maximal possible size
void reserve(size_type); // reserve space, only available if (has_reserve == true)
// heap equivalence
template<typename HeapType> bool operator==(HeapType const &) const;
template<typename HeapType> bool operator!=(HeapType const &) const;
// heap comparison
template<typename HeapType> bool operator<(HeapType const &) const;
template<typename HeapType> bool operator>(HeapType const &) const;
template<typename HeapType> bool operator>=(HeapType const &) const;
template<typename HeapType> bool operator<=(HeapType const &) const;
// public data members
static const bool constant_time_size; // size() has constant complexity
static const bool has_ordered_iterators; // priority queue has ``[link heap.concepts.iterators ordered iterators]``
static const bool is_mergable; // priority queue is efficiently ``[link heap.concepts.merge mergable]``
static const bool is_stable; // priority queue has a ``[link heap.concepts.stability stable heap order]``
static const bool has_reserve; // priority queue has a reserve() member
};
[h5 Example]
[import ../examples/interface.cpp]
[basic_interface]
[endsect]
[section:iterators Priority Queue Iterators]
[h5 Synopsis]
class iteratable_heap_interface
{
public:
// types
typedef ``/unspecified/`` iterator;
typedef ``/unspecified/`` const_iterator;
typedef ``/unspecified/`` ordered_iterator;
// public member functions
iterator begin(void) const;
iterator end(void) const;
ordered_iterator ordered_begin(void) const;
ordered_iterator ordered_end(void) const;
};
Priority queues provide iterators, that can be used to traverse their elements. All heap iterators are const_iterators, that means
they cannot be used to modify the values, because changing the value of a heap node may corrupt the heap order. Details about
modifying heap nodes are described in the section about the [link heap.concepts.mutability mutability interface].
Iterators do not visit heap elements in any specific order. Unless otherwise noted, all non-const heap member functions invalidate
iterators, while all const member functions preserve the iterator validity.
[note Some implementations require iterators, that contain a set of elements, that are *discovered*, but not *visited*. Therefore
copying iterators can be inefficient and should be avoided.]
[h5 Example]
[iterator_interface]
[section:ordered_iterators Ordered Iterators]
Except for [classref boost::heap::priority_queue] all _heap_ data structures support ordered iterators, which visit all elements
of the heap in heap-order. The implementation of these [^ordered_iterator]s requires some internal bookkeeping, so iterating the a
heap in heap order has an amortized complexity of O(N*log(N)).
[h5 Example]
[ordered_iterator_interface]
[endsect]
[endsect]
[section:comparing Comparing Priority Queues & Equivalence]
The data structures of _heap_ can be compared with standard comparison operators. The comparison is performed by comparing two
heaps element by element using =value_compare=.
[note Depending on the heap type, this operation can be rather expensive, because both data structures need to be traversed in
heap order. On heaps without ordered iterators, the heap needs to be copied internally. The typical complexity is O(n log(n)).]
[endsect]
[section:merge Merging Priority Queues]
[h3 Mergable Priority Queues]
[h5 Synopsis]
class mergable_heap_interface
{
public:
// public member functions
void merge(mergable_heap_interface &);
};
_heap_ has a concept of a Mergable Priority Queue. A mergable priority queue can efficiently be merged with a different instance
of the same type.
[h5 Example]
[merge_interface]
[h3 Heap Merge Algorithms]
_heap_ provides a =heap_merge()= algorithm that is can be used to merge different kinds of heaps. Using this algorithm, all _heap_
data structures can be merged, although some cannot be merged efficiently.
[h5 Example]
[heap_merge_algorithm]
[endsect]
[section:mutability Mutability]
Some priority queues of _heap_ are mutable, that means the priority of their elements can be changed. To achieve mutability,
_heap_ introduces the concept of *handles*, which can be used to access the internal nodes of the priority queue in order to
change its value and to restore the heap order.
[h5 Synopsis]
class mutable_heap_interface
{
public:
typedef ``/unspecified/`` iterator;
struct handle_type
{
value_type & operator*() const;
};
static handle_type s_iterator_to_handle(iterator const &);
// priority queue interface
handle_type push(T const & v);
// update element via assignment and fix heap
void update(handle_type const & handle, value_type const & v);
void increase(handle_type const & handle, value_type const & v);
void decrease(handle_type const & handle, value_type const & v);
// fix heap after element has been changed via the handle
void update(handle_type const & handle);
void increase(handle_type const & handle);
void decrease(handle_type const & handle);
};
[warning Incorrect use of =increase= or =decrease= may corrupt the priority queue data structure. If unsure use =update= can be
used at the cost of efficiency.]
[h5 Example]
[mutable_interface]
Note that handles can be stored inside the =value_type=:
[mutable_interface_handle_in_value]
[h3 The Fixup Interface]
There are two different APIs to support mutability. The first family of functions provides update functionality by changing
the current element by assigning a new value. The second family of functions can be used to fix the heap data structure after
an element has been changed directly via a handle. While this provides the user with a means to modify the priority of queue
elements without the need to change their non-priority part, this needs to be handled with care. The heap needs to be fixed up
immediately after the priority of the element has been changed.
Beside an =update= function, two additional functions =increase= and =decrease= are provided, that are generally more efficient
than the generic =update= function. However the user has do ensure, that the priority of an element is changed to the right
direction.
[h5 Example]
[mutable_fixup_interface]
Iterators can be coverted to handles using the static member function =s_handle_from_iterator=. However most implementations of
=update= invalidate all iterators. The most notable exception is the [classref boost::heap::fibonacci_heap fibonacci heap],
providing a lazy update function, that just invalidates the iterators, that are related to this handle.
[warning After changing the priority via a handle, the heap needs to be fixed by calling one of the update functions. Otherwise the
priority queue structure may be corrupted!]
[endsect]
[section:stability Stability]
A priority queue is `stable', if elements with the same priority are popped from the heap, in the same order as
they are inserted. The data structures provided by _heap_, can be configured to be stable at compile time using the
[classref boost::heap::stable] policy. Two notions of stability are supported. If a heap is configured with *no stability*,
the order of nodes of the same priority is undefined, if it is configured as *stable*, nodes of the same priority are ordered by
their insertion time.
Stability is achieved by associating an integer version count with each value in order to distinguish values with the same node.
The type of this version count defaults to =boost::uintmax_t=, which is at least 64bit on most systems. However it can be
configured to use a different type using the [classref boost::heap::stability_counter_type] template argument.
[warning The stability counter is prone to integer overflows. If an overflow occurs during a =push()= call, the operation
will fail and an exception is thrown. Later =push()= call will succeed, but the stable heap order will be compromised. However an
integer overflow at 64bit is very unlikely: if an application would issue one =push()= operation per microsecond, the value will
overflow in more than 500000 years.]
[endsect]
[endsect]
[section:data_structures Data Structures]
_heap_ provides the following data structures:
[variablelist
[[[classref boost::heap::priority_queue]]
[
The [classref boost::heap::priority_queue priority_queue] class is a wrapper to the stl heap functions. It implements
a heap as container adaptor ontop of a =std::vector= and is immutable.
]
]
[[[classref boost::heap::d_ary_heap]]
[
[@http://en.wikipedia.org/wiki/D-ary_heap D-ary heaps] are a generalization of binary heap with each non-leaf node
having N children. For a low arity, the height of the heap is larger, but the number of comparisons to find the largest
child node is bigger. D-ary heaps are implemented as container adaptors based on a =std::vector=.
The data structure can be configured as mutable. This is achieved by storing the values inside a std::list.
]
]
[[[classref boost::heap::binomial_heap]]
[
[@http://en.wikipedia.org/wiki/Binomial_heap Binomial heaps] are node-base heaps, that are implemented as a set of
binomial trees of piecewise different order. The most important heap operations have a worst-case complexity of O(log n).
In contrast to d-ary heaps, binomial heaps can also be merged in O(log n).
]
]
[[[classref boost::heap::fibonacci_heap]]
[
[@http://en.wikipedia.org/wiki/Fibonacci_heap Fibonacci heaps] are node-base heaps, that are implemented as a forest of
heap-ordered trees. They provide better amortized performance than binomial heaps. Except =pop()= and =erase()=, the most
important heap operations have constant amortized complexity.
]
]
[[[classref boost::heap::pairing_heap]]
[
[@http://en.wikipedia.org/wiki/Pairing_heap Pairing heaps] are self-adjusting node-based heaps. Although design and
implementation are rather simple, the complexity analysis is yet unsolved. For details, consult:
Pettie, Seth (2005), "Towards a final analysis of pairing heaps", Proc. 46th Annual IEEE Symposium on Foundations of Computer Science, pp. 174–183
]
]
[[[classref boost::heap::skew_heap]]
[
[@http://en.wikipedia.org/wiki/Skew_heap Skew heaps] are self-adjusting node-based heaps. Although there are no
constraints for the tree structure, all heap operations can be performed in O(log n).
]
]
]
[table Comparison of amortized complexity
[[] [[^top()]] [[^push()]] [[^pop()]] [[^update()]] [[^increase()]] [[^decrease()]] [[^erase()]] [[^merge_and_clear()]]]
[[[classref boost::heap::priority_queue]] [[^O(1)]] [O(log(N))] [O(log(N))] [n/a] [n/a] [n/a] [n/a] [O((N+M)*log(N+M))]]
[[[classref boost::heap::d_ary_heap]] [[^O(1)]] [O(log(N))] [O(log(N))] [O(log(N))] [O(log(N))] [O(log(N))] [O(log(N))] [O((N+M)*log(N+M))]]
[[[classref boost::heap::binomial_heap]] [[^O(1)]] [O(log(N))] [O(log(N))] [O(log(N))] [O(log(N))] [O(log(N))] [O(log(N))] [O(log(N+M))]]
[[[classref boost::heap::fibonacci_heap]] [[^O(1)]] [O(1)] [O(log(N))] [O(log(N))
[footnote The fibonacci a [^update_lazy()] method, which has O(log(N)) amortized complexity as well, but does not try to consolidate the internal forest]
] [O(1)] [O(log(N))] [O(log(N))] [O(1)]]
[[[classref boost::heap::pairing_heap]] [[^O(1)]] [O(2**2*log(log(N)))] [O(log(N))] [O(2**2*log(log(N)))] [O(2**2*log(log(N)))] [O(2**2*log(log(N)))] [O(2**2*log(log(N)))] [O(2**2*log(log(N)))]]
[[[classref boost::heap::skew_heap]] [[^O(1)]] [O(log(N))] [O(log(N))] [O(log(N))] [O(log(N))] [O(log(N))] [O(log(N))] [O(log(N+M))]]
]
[section Data Structure Configuration]
The data structures can be configured with [@boost:/libs/parameter/doc/html/index.html Boost.Parameter]-style templates.
[variablelist
[[[classref boost::heap::compare]]
[Predicate for defining the heap order, optional
(defaults to =boost::heap::compare<std::less<T> >=)]
]
[[[classref boost::heap::allocator]]
[Allocator for internal memory management, optional
(defaults to =boost::heap::allocator<std::allocator<T> >=)]
]
[[[classref boost::heap::stable]]
[Configures the heap to use a [link heap.concepts.stability stable heap order], optional (defaults to =boost::heap::stable<false>=).
]
]
[[[classref boost::heap::mutable_]]
[Configures the heap to be mutable. [classref boost::heap::d_ary_heap] and [classref boost::heap::skew_heap] have to be configured
with this policy to enable the [link heap.concepts.mutability mutability interface].
]
]
[[[classref boost::heap::stability_counter_type]]
[Configures the integer type used for the stability counter, optional (defaults to =boost::heap::stability_counter_type<boost::uintmax_t>=).
For more details, consult the [link heap.concepts.stability Stability] section.
]
]
[[[classref boost::heap::constant_time_size]]
[Specifies, whether =size()= should have linear or constant complexity. This argument is only available for node-based
heap data structures and if available, it is optional (defaults to =boost::heap::constant_time_size<true>=)]
]
[[[classref boost::heap::arity]]
[Specifies the arity of a d-ary heap. For details, please consult the class reference of [classref boost::heap::d_ary_heap]]
]
[[[classref boost::heap::store_parent_pointer]]
[Store the parent pointer in the heap nodes. This policy is only available in the [classref boost::heap::skew_heap].
]
]
]
[endsect]
[endsect]
[xinclude autodoc.xml]
[section Acknowledgements]
[variablelist
[[Google Inc.]
[For sponsoring the development of this library during the Summer of Code 2010]
]
[[Hartmut Kaiser]
[For mentoring the Summer of Code project]
]
]
[endsect]