1390f4ba63
Found via `codespell -q 3 -L tim,que,numer`
422 lines
18 KiB
Plaintext
422 lines
18 KiB
Plaintext
[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 converted 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] |