first commit

This commit is contained in:
murdle
2026-03-01 02:38:58 +02:00
commit 19250b9db4
19111 changed files with 4358159 additions and 0 deletions

View File

@@ -0,0 +1,922 @@
// boost heap: binomial heap
//
// Copyright (C) 2010 Tim Blechmann
//
// 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_HEAP_BINOMIAL_HEAP_HPP
#define BOOST_HEAP_BINOMIAL_HEAP_HPP
#include <algorithm>
#include <utility>
#include <vector>
#include <boost/assert.hpp>
#include <boost/heap/detail/heap_comparison.hpp>
#include <boost/heap/detail/heap_node.hpp>
#include <boost/heap/detail/stable_heap.hpp>
#include <boost/heap/detail/tree_iterator.hpp>
#ifndef BOOST_DOXYGEN_INVOKED
#ifdef BOOST_HEAP_SANITYCHECKS
#define BOOST_HEAP_ASSERT BOOST_ASSERT
#else
#define BOOST_HEAP_ASSERT(expression)
#endif
#endif
namespace boost {
namespace heap {
namespace detail {
typedef parameter::parameters<boost::parameter::optional<tag::allocator>,
boost::parameter::optional<tag::compare>,
boost::parameter::optional<tag::stable>,
boost::parameter::optional<tag::constant_time_size>,
boost::parameter::optional<tag::stability_counter_type>
> binomial_heap_signature;
template <typename T, typename Parspec>
struct make_binomial_heap_base
{
static const bool constant_time_size = parameter::binding<Parspec,
tag::constant_time_size,
boost::mpl::true_
>::type::value;
typedef typename detail::make_heap_base<T, Parspec, constant_time_size>::type base_type;
typedef typename detail::make_heap_base<T, Parspec, constant_time_size>::allocator_argument allocator_argument;
typedef typename detail::make_heap_base<T, Parspec, constant_time_size>::compare_argument compare_argument;
typedef parent_pointing_heap_node<typename base_type::internal_type> node_type;
typedef typename allocator_argument::template rebind<node_type>::other allocator_type;
struct type:
base_type,
allocator_type
{
type(compare_argument const & arg):
base_type(arg)
{}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
type(type const & rhs):
base_type(rhs), allocator_type(rhs)
{}
type(type && rhs):
base_type(std::move(static_cast<base_type&>(rhs))),
allocator_type(std::move(static_cast<allocator_type&>(rhs)))
{}
type & operator=(type && rhs)
{
base_type::operator=(std::move(static_cast<base_type&>(rhs)));
allocator_type::operator=(std::move(static_cast<allocator_type&>(rhs)));
return *this;
}
type & operator=(type const & rhs)
{
base_type::operator=(static_cast<base_type const &>(rhs));
allocator_type::operator=(static_cast<allocator_type const &>(rhs));
return *this;
}
#endif
};
};
}
/**
* \class binomial_heap
* \brief binomial heap
*
* The template parameter T is the type to be managed by the container.
* The user can specify additional options and if no options are provided default options are used.
*
* The container supports the following options:
* - \c boost::heap::stable<>, defaults to \c stable<false>
* - \c boost::heap::compare<>, defaults to \c compare<std::less<T> >
* - \c boost::heap::allocator<>, defaults to \c allocator<std::allocator<T> >
* - \c boost::heap::constant_time_size<>, defaults to \c constant_time_size<true>
* - \c boost::heap::stability_counter_type<>, defaults to \c stability_counter_type<boost::uintmax_t>
*
*/
#ifdef BOOST_DOXYGEN_INVOKED
template<class T, class ...Options>
#else
template <typename T,
class A0 = boost::parameter::void_,
class A1 = boost::parameter::void_,
class A2 = boost::parameter::void_,
class A3 = boost::parameter::void_
>
#endif
class binomial_heap:
private detail::make_binomial_heap_base<T,
typename detail::binomial_heap_signature::bind<A0, A1, A2, A3>::type
>::type
{
typedef typename detail::binomial_heap_signature::bind<A0, A1, A2, A3>::type bound_args;
typedef detail::make_binomial_heap_base<T, bound_args> base_maker;
typedef typename base_maker::type super_t;
typedef typename super_t::internal_type internal_type;
typedef typename super_t::size_holder_type size_holder;
typedef typename base_maker::allocator_argument allocator_argument;
template <typename Heap1, typename Heap2>
friend struct heap_merge_emulate;
public:
static const bool constant_time_size = super_t::constant_time_size;
static const bool has_ordered_iterators = true;
static const bool is_mergable = true;
static const bool is_stable = detail::extract_stable<bound_args>::value;
static const bool has_reserve = false;
private:
#ifndef BOOST_DOXYGEN_INVOKED
struct implementation_defined:
detail::extract_allocator_types<typename base_maker::allocator_argument>
{
typedef T value_type;
typedef typename detail::extract_allocator_types<typename base_maker::allocator_argument>::size_type size_type;
typedef typename detail::extract_allocator_types<typename base_maker::allocator_argument>::reference reference;
typedef typename base_maker::compare_argument value_compare;
typedef typename base_maker::allocator_type allocator_type;
typedef typename base_maker::node_type node;
typedef typename allocator_type::pointer node_pointer;
typedef typename allocator_type::const_pointer const_node_pointer;
typedef detail::node_handle<node_pointer, super_t, reference> handle_type;
typedef typename base_maker::node_type node_type;
typedef boost::intrusive::list<detail::heap_node_base<false>,
boost::intrusive::constant_time_size<true>
> node_list_type;
typedef typename node_list_type::iterator node_list_iterator;
typedef typename node_list_type::const_iterator node_list_const_iterator;
typedef detail::value_extractor<value_type, internal_type, super_t> value_extractor;
typedef detail::recursive_tree_iterator<node_type,
node_list_const_iterator,
const value_type,
value_extractor,
detail::list_iterator_converter<node_type, node_list_type>
> iterator;
typedef iterator const_iterator;
typedef detail::tree_iterator<node_type,
const value_type,
allocator_type,
value_extractor,
detail::list_iterator_converter<node_type, node_list_type>,
true,
true,
value_compare
> ordered_iterator;
};
#endif
public:
typedef T value_type;
typedef typename implementation_defined::size_type size_type;
typedef typename implementation_defined::difference_type difference_type;
typedef typename implementation_defined::value_compare value_compare;
typedef typename implementation_defined::allocator_type allocator_type;
typedef typename implementation_defined::reference reference;
typedef typename implementation_defined::const_reference const_reference;
typedef typename implementation_defined::pointer pointer;
typedef typename implementation_defined::const_pointer const_pointer;
/// \copydoc boost::heap::priority_queue::iterator
typedef typename implementation_defined::iterator iterator;
typedef typename implementation_defined::const_iterator const_iterator;
typedef typename implementation_defined::ordered_iterator ordered_iterator;
typedef typename implementation_defined::handle_type handle_type;
private:
typedef typename implementation_defined::node_type node_type;
typedef typename implementation_defined::node_list_type node_list_type;
typedef typename implementation_defined::node_pointer node_pointer;
typedef typename implementation_defined::const_node_pointer const_node_pointer;
typedef typename implementation_defined::node_list_iterator node_list_iterator;
typedef typename implementation_defined::node_list_const_iterator node_list_const_iterator;
typedef typename super_t::internal_compare internal_compare;
public:
/// \copydoc boost::heap::priority_queue::priority_queue(value_compare const &)
explicit binomial_heap(value_compare const & cmp = value_compare()):
super_t(cmp), top_element(0)
{}
/// \copydoc boost::heap::priority_queue::priority_queue(priority_queue const &)
binomial_heap(binomial_heap const & rhs):
super_t(rhs), top_element(0)
{
if (rhs.empty())
return;
clone_forest(rhs);
size_holder::set_size(rhs.get_size());
}
/// \copydoc boost::heap::priority_queue::operator=(priority_queue const &)
binomial_heap & operator=(binomial_heap const & rhs)
{
clear();
size_holder::set_size(rhs.get_size());
static_cast<super_t&>(*this) = rhs;
if (rhs.empty())
top_element = NULL;
else
clone_forest(rhs);
return *this;
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
/// \copydoc boost::heap::priority_queue::priority_queue(priority_queue &&)
binomial_heap(binomial_heap && rhs):
super_t(std::move(rhs)), top_element(rhs.top_element)
{
trees.splice(trees.begin(), rhs.trees);
rhs.top_element = NULL;
}
/// \copydoc boost::heap::priority_queue::operator=(priority_queue &&)
binomial_heap & operator=(binomial_heap && rhs)
{
clear();
super_t::operator=(std::move(rhs));
trees.splice(trees.begin(), rhs.trees);
top_element = rhs.top_element;
rhs.top_element = NULL;
return *this;
}
#endif
~binomial_heap(void)
{
clear();
}
/// \copydoc boost::heap::priority_queue::empty
bool empty(void) const
{
return top_element == NULL;
}
/**
* \b Effects: Returns the number of elements contained in the priority queue.
*
* \b Complexity: Constant, if configured with constant_time_size<true>, otherwise linear.
*
* */
size_type size(void) const
{
if (constant_time_size)
return size_holder::get_size();
if (empty())
return 0;
else
return detail::count_list_nodes<node_type, node_list_type>(trees);
}
/// \copydoc boost::heap::priority_queue::max_size
size_type max_size(void) const
{
return allocator_type::max_size();
}
/// \copydoc boost::heap::priority_queue::clear
void clear(void)
{
typedef detail::node_disposer<node_type, typename node_list_type::value_type, allocator_type> disposer;
trees.clear_and_dispose(disposer(*this));
size_holder::set_size(0);
top_element = NULL;
}
/// \copydoc boost::heap::priority_queue::get_allocator
allocator_type get_allocator(void) const
{
return *this;
}
/// \copydoc boost::heap::priority_queue::swap
void swap(binomial_heap & rhs)
{
super_t::swap(rhs);
std::swap(top_element, rhs.top_element);
trees.swap(rhs.trees);
}
/// \copydoc boost::heap::priority_queue::top
const_reference top(void) const
{
BOOST_ASSERT(!empty());
return super_t::get_value(top_element->value);
}
/**
* \b Effects: Adds a new element to the priority queue. Returns handle to element
*
* \b Complexity: Logarithmic.
*
* */
handle_type push(value_type const & v)
{
node_pointer n = allocator_type::allocate(1);
new(n) node_type(super_t::make_node(v));
insert_node(trees.begin(), n);
if (!top_element || super_t::operator()(top_element->value, n->value))
top_element = n;
size_holder::increment();
sanity_check();
return handle_type(n);
}
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
/**
* \b Effects: Adds a new element to the priority queue. The element is directly constructed in-place. Returns handle to element.
*
* \b Complexity: Logarithmic.
*
* */
template <class... Args>
handle_type emplace(Args&&... args)
{
node_pointer n = allocator_type::allocate(1);
new(n) node_type(super_t::make_node(std::forward<Args>(args)...));
insert_node(trees.begin(), n);
if (!top_element || super_t::operator()(top_element->value, n->value))
top_element = n;
size_holder::increment();
sanity_check();
return handle_type(n);
}
#endif
/**
* \b Effects: Removes the top element from the priority queue.
*
* \b Complexity: Logarithmic.
*
* */
void pop(void)
{
BOOST_ASSERT(!empty());
node_pointer element = top_element;
trees.erase(node_list_type::s_iterator_to(*element));
size_holder::decrement();
if (element->child_count()) {
size_type sz = (1 << element->child_count()) - 1;
binomial_heap children(value_comp(), element->children, sz);
if (trees.empty())
swap(children);
else
merge_and_clear_nodes(children);
}
if (trees.empty())
top_element = NULL;
else
update_top_element();
element->~node_type();
allocator_type::deallocate(element, 1);
sanity_check();
}
/**
* \b Effects: Assigns \c v to the element handled by \c handle & updates the priority queue.
*
* \b Complexity: Logarithmic.
*
* */
void update (handle_type handle, const_reference v)
{
if (super_t::operator()(super_t::get_value(handle.node_->value), v))
increase(handle, v);
else
decrease(handle, v);
}
/**
* \b Effects: Updates the heap after the element handled by \c handle has been changed.
*
* \b Complexity: Logarithmic.
*
* \b Note: If this is not called, after a handle has been updated, the behavior of the data structure is undefined!
* */
void update (handle_type handle)
{
node_pointer this_node = handle.node_;
if (this_node->parent) {
if (super_t::operator()(super_t::get_value(this_node->parent->value), super_t::get_value(this_node->value)))
increase(handle);
else
decrease(handle);
}
else
decrease(handle);
}
/**
* \b Effects: Assigns \c v to the element handled by \c handle & updates the priority queue.
*
* \b Complexity: Logarithmic.
*
* \b Note: The new value is expected to be greater than the current one
* */
void increase (handle_type handle, const_reference v)
{
handle.node_->value = super_t::make_node(v);
increase(handle);
}
/**
* \b Effects: Updates the heap after the element handled by \c handle has been changed.
*
* \b Complexity: Logarithmic.
*
* \b Note: If this is not called, after a handle has been updated, the behavior of the data structure is undefined!
* */
void increase (handle_type handle)
{
node_pointer n = handle.node_;
siftup(n, *this);
update_top_element();
sanity_check();
}
/**
* \b Effects: Assigns \c v to the element handled by \c handle & updates the priority queue.
*
* \b Complexity: Logarithmic.
*
* \b Note: The new value is expected to be less than the current one
* */
void decrease (handle_type handle, const_reference v)
{
handle.node_->value = super_t::make_node(v);
decrease(handle);
}
/**
* \b Effects: Updates the heap after the element handled by \c handle has been changed.
*
* \b Complexity: Logarithmic.
*
* \b Note: The new value is expected to be less than the current one. If this is not called, after a handle has been updated, the behavior of the data structure is undefined!
* */
void decrease (handle_type handle)
{
node_pointer n = handle.node_;
siftdown(n);
if (n == top_element)
update_top_element();
}
/**
* \b Effects: Merge with priority queue rhs.
*
* \b Complexity: Logarithmic.
*
* */
void merge(binomial_heap & rhs)
{
if (rhs.empty())
return;
if (empty()) {
swap(rhs);
return;
}
size_type new_size = size_holder::get_size() + rhs.get_size();
merge_and_clear_nodes(rhs);
size_holder::set_size(new_size);
rhs.set_size(0);
rhs.top_element = NULL;
super_t::set_stability_count((std::max)(super_t::get_stability_count(),
rhs.get_stability_count()));
rhs.set_stability_count(0);
}
public:
/// \copydoc boost::heap::priority_queue::begin
iterator begin(void) const
{
return iterator(trees.begin());
}
/// \copydoc boost::heap::priority_queue::end
iterator end(void) const
{
return iterator(trees.end());
}
/// \copydoc boost::heap::fibonacci_heap::ordered_begin
ordered_iterator ordered_begin(void) const
{
return ordered_iterator(trees.begin(), trees.end(), top_element, super_t::value_comp());
}
/// \copydoc boost::heap::fibonacci_heap::ordered_end
ordered_iterator ordered_end(void) const
{
return ordered_iterator(NULL, super_t::value_comp());
}
/**
* \b Effects: Removes the element handled by \c handle from the priority_queue.
*
* \b Complexity: Logarithmic.
* */
void erase(handle_type handle)
{
node_pointer n = handle.node_;
siftup(n, force_inf());
top_element = n;
pop();
}
/// \copydoc boost::heap::d_ary_heap_mutable::s_handle_from_iterator
static handle_type s_handle_from_iterator(iterator const & it)
{
node_type * ptr = const_cast<node_type *>(it.get_node());
return handle_type(ptr);
}
/// \copydoc boost::heap::priority_queue::value_comp
value_compare const & value_comp(void) const
{
return super_t::value_comp();
}
/// \copydoc boost::heap::priority_queue::operator<(HeapType const & rhs) const
template <typename HeapType>
bool operator<(HeapType const & rhs) const
{
return detail::heap_compare(*this, rhs);
}
/// \copydoc boost::heap::priority_queue::operator>(HeapType const & rhs) const
template <typename HeapType>
bool operator>(HeapType const & rhs) const
{
return detail::heap_compare(rhs, *this);
}
/// \copydoc boost::heap::priority_queue::operator>=(HeapType const & rhs) const
template <typename HeapType>
bool operator>=(HeapType const & rhs) const
{
return !operator<(rhs);
}
/// \copydoc boost::heap::priority_queue::operator<=(HeapType const & rhs) const
template <typename HeapType>
bool operator<=(HeapType const & rhs) const
{
return !operator>(rhs);
}
/// \copydoc boost::heap::priority_queue::operator==(HeapType const & rhs) const
template <typename HeapType>
bool operator==(HeapType const & rhs) const
{
return detail::heap_equality(*this, rhs);
}
/// \copydoc boost::heap::priority_queue::operator!=(HeapType const & rhs) const
template <typename HeapType>
bool operator!=(HeapType const & rhs) const
{
return !(*this == rhs);
}
private:
#if !defined(BOOST_DOXYGEN_INVOKED)
void merge_and_clear_nodes(binomial_heap & rhs)
{
BOOST_HEAP_ASSERT (!empty());
BOOST_HEAP_ASSERT (!rhs.empty());
node_list_iterator this_iterator = trees.begin();
node_pointer carry_node = NULL;
while (!rhs.trees.empty()) {
node_pointer rhs_node = static_cast<node_pointer>(&rhs.trees.front());
size_type rhs_degree = rhs_node->child_count();
if (super_t::operator()(top_element->value, rhs_node->value))
top_element = rhs_node;
try_again:
node_pointer this_node = static_cast<node_pointer>(&*this_iterator);
size_type this_degree = this_node->child_count();
sorted_by_degree();
rhs.sorted_by_degree();
if (this_degree == rhs_degree) {
if (carry_node) {
if (carry_node->child_count() < this_degree) {
trees.insert(this_iterator, *carry_node);
carry_node = NULL;
} else {
rhs.trees.pop_front();
carry_node = merge_trees(carry_node, rhs_node);
}
++this_iterator;
} else {
this_iterator = trees.erase(this_iterator);
rhs.trees.pop_front();
carry_node = merge_trees(this_node, rhs_node);
}
if (this_iterator == trees.end())
break;
else
continue;
}
if (this_degree < rhs_degree) {
if (carry_node) {
if (carry_node->child_count() < this_degree) {
trees.insert(this_iterator, *carry_node);
carry_node = NULL;
++this_iterator;
} else if (carry_node->child_count() == rhs_degree) {
rhs.trees.pop_front();
carry_node = merge_trees(carry_node, rhs_node);
continue;
} else {
this_iterator = trees.erase(this_iterator);
carry_node = merge_trees(this_node, carry_node);
}
goto try_again;
} else {
++this_iterator;
if (this_iterator == trees.end())
break;
goto try_again;
}
if (this_iterator == trees.end())
break;
else
continue;
}
if (this_degree > rhs_degree) {
rhs.trees.pop_front();
if (carry_node) {
if (carry_node->child_count() < rhs_degree) {
trees.insert(this_iterator, *carry_node);
trees.insert(this_iterator, *rhs_node);
carry_node = NULL;
} else
carry_node = merge_trees(rhs_node, carry_node);
} else
trees.insert(this_iterator, *rhs_node);
}
}
if (!rhs.trees.empty()) {
if (carry_node) {
node_list_iterator rhs_it = rhs.trees.begin();
while (static_cast<node_pointer>(&*rhs_it)->child_count() < carry_node->child_count())
++rhs_it;
rhs.insert_node(rhs_it, carry_node);
rhs.increment();
sorted_by_degree();
rhs.sorted_by_degree();
if (trees.empty()) {
trees.splice(trees.end(), rhs.trees, rhs.trees.begin(), rhs.trees.end());
update_top_element();
} else
merge_and_clear_nodes(rhs);
} else
trees.splice(trees.end(), rhs.trees, rhs.trees.begin(), rhs.trees.end());
return;
}
if (carry_node)
insert_node(this_iterator, carry_node);
}
void clone_forest(binomial_heap const & rhs)
{
BOOST_HEAP_ASSERT(trees.empty());
typedef typename node_type::template node_cloner<allocator_type> node_cloner;
trees.clone_from(rhs.trees, node_cloner(*this, NULL), detail::nop_disposer());
update_top_element();
}
struct force_inf
{
template <typename X>
bool operator()(X const &, X const &) const
{
return false;
}
};
template <typename Compare>
void siftup(node_pointer n, Compare const & cmp)
{
while (n->parent) {
node_pointer parent = n->parent;
node_pointer grand_parent = parent->parent;
if (cmp(n->value, parent->value))
return;
n->remove_from_parent();
n->swap_children(parent);
n->update_children();
parent->update_children();
if (grand_parent) {
parent->remove_from_parent();
grand_parent->add_child(n);
} else {
node_list_iterator it = trees.erase(node_list_type::s_iterator_to(*parent));
trees.insert(it, *n);
}
n->add_child(parent);
BOOST_HEAP_ASSERT(parent->child_count() == n->child_count());
}
}
void siftdown(node_pointer n)
{
while (n->child_count()) {
node_pointer max_child = detail::find_max_child<node_list_type, node_type, internal_compare>(n->children, super_t::get_internal_cmp());
if (super_t::operator()(max_child->value, n->value))
return;
max_child->remove_from_parent();
n->swap_children(max_child);
n->update_children();
max_child->update_children();
node_pointer parent = n->parent;
if (parent) {
n->remove_from_parent();
max_child->add_child(n);
parent->add_child(max_child);
} else {
node_list_iterator position = trees.erase(node_list_type::s_iterator_to(*n));
max_child->add_child(n);
trees.insert(position, *max_child);
}
}
}
void insert_node(node_list_iterator it, node_pointer n)
{
if (it != trees.end())
BOOST_HEAP_ASSERT(static_cast<node_pointer>(&*it)->child_count() >= n->child_count());
while(true) {
BOOST_HEAP_ASSERT(!n->is_linked());
if (it == trees.end())
break;
node_pointer this_node = static_cast<node_pointer>(&*it);
size_type this_degree = this_node->child_count();
size_type n_degree = n->child_count();
if (this_degree == n_degree) {
BOOST_HEAP_ASSERT(it->is_linked());
it = trees.erase(it);
n = merge_trees(n, this_node);
} else
break;
}
trees.insert(it, *n);
}
// private constructor, just used in pop()
explicit binomial_heap(value_compare const & cmp, node_list_type & child_list, size_type size):
super_t(cmp)
{
size_holder::set_size(size);
if (size)
top_element = static_cast<node_pointer>(&*child_list.begin()); // not correct, but we will reset it later
else
top_element = NULL;
for (node_list_iterator it = child_list.begin(); it != child_list.end(); ++it) {
node_pointer n = static_cast<node_pointer>(&*it);
n->parent = NULL;
}
trees.splice(trees.end(), child_list, child_list.begin(), child_list.end());
trees.sort(detail::cmp_by_degree<node_type>());
}
node_pointer merge_trees (node_pointer node1, node_pointer node2)
{
BOOST_HEAP_ASSERT(node1->child_count() == node2->child_count());
if (super_t::operator()(node1->value, node2->value))
std::swap(node1, node2);
if (node2->parent)
node2->remove_from_parent();
node1->add_child(node2);
return node1;
}
void update_top_element(void)
{
top_element = detail::find_max_child<node_list_type, node_type, internal_compare>(trees, super_t::get_internal_cmp());
}
void sorted_by_degree(void) const
{
#ifdef BOOST_HEAP_SANITYCHECKS
int degree = -1;
for (node_list_const_iterator it = trees.begin(); it != trees.end(); ++it) {
const_node_pointer n = static_cast<const_node_pointer>(&*it);
BOOST_HEAP_ASSERT(int(n->child_count()) > degree);
degree = n->child_count();
BOOST_HEAP_ASSERT((detail::is_heap<node_type, super_t>(n, *this)));
size_type child_nodes = detail::count_nodes<node_type>(n);
BOOST_HEAP_ASSERT(child_nodes == size_type(1 << static_cast<const_node_pointer>(&*it)->child_count()));
}
#endif
}
void sanity_check(void)
{
#ifdef BOOST_HEAP_SANITYCHECKS
sorted_by_degree();
if (!empty()) {
node_pointer found_top = detail::find_max_child<node_list_type, node_type, internal_compare>(trees, super_t::get_internal_cmp());
BOOST_HEAP_ASSERT(top_element == found_top);
}
if (constant_time_size) {
size_t counted = detail::count_list_nodes<node_type, node_list_type>(trees);
size_t stored = size_holder::get_size();
BOOST_HEAP_ASSERT(counted == stored);
}
#endif
}
node_pointer top_element;
node_list_type trees;
#endif // BOOST_DOXYGEN_INVOKED
};
} /* namespace heap */
} /* namespace boost */
#undef BOOST_HEAP_ASSERT
#endif /* BOOST_HEAP_D_ARY_HEAP_HPP */

View File

@@ -0,0 +1,821 @@
// // boost heap: d-ary heap as containter adaptor
//
// Copyright (C) 2010 Tim Blechmann
//
// 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_HEAP_D_ARY_HEAP_HPP
#define BOOST_HEAP_D_ARY_HEAP_HPP
#include <algorithm>
#include <utility>
#include <vector>
#include <boost/assert.hpp>
#include <boost/mem_fn.hpp>
#include <boost/heap/detail/heap_comparison.hpp>
#include <boost/heap/detail/ordered_adaptor_iterator.hpp>
#include <boost/heap/detail/stable_heap.hpp>
#include <boost/heap/detail/mutable_heap.hpp>
#ifndef BOOST_DOXYGEN_INVOKED
#ifdef BOOST_HEAP_SANITYCHECKS
#define BOOST_HEAP_ASSERT BOOST_ASSERT
#else
#define BOOST_HEAP_ASSERT(expression)
#endif
#endif
namespace boost {
namespace heap {
namespace detail {
struct nop_index_updater
{
template <typename T>
static void run(T &, std::size_t)
{}
};
typedef parameter::parameters<boost::parameter::required<tag::arity>,
boost::parameter::optional<tag::allocator>,
boost::parameter::optional<tag::compare>,
boost::parameter::optional<tag::stable>,
boost::parameter::optional<tag::stability_counter_type>,
boost::parameter::optional<tag::constant_time_size>
> d_ary_heap_signature;
/* base class for d-ary heap */
template <typename T,
class BoundArgs,
class IndexUpdater>
class d_ary_heap:
private make_heap_base<T, BoundArgs, false>::type
{
typedef make_heap_base<T, BoundArgs, false> heap_base_maker;
typedef typename heap_base_maker::type super_t;
typedef typename super_t::internal_type internal_type;
typedef typename heap_base_maker::allocator_argument::template rebind<internal_type>::other internal_type_allocator;
typedef std::vector<internal_type, internal_type_allocator> container_type;
typedef typename container_type::const_iterator container_iterator;
typedef IndexUpdater index_updater;
container_type q_;
static const unsigned int D = parameter::binding<BoundArgs, tag::arity>::type::value;
template <typename Heap1, typename Heap2>
friend struct heap_merge_emulate;
struct implementation_defined:
extract_allocator_types<typename heap_base_maker::allocator_argument>
{
typedef T value_type;
typedef typename detail::extract_allocator_types<typename heap_base_maker::allocator_argument>::size_type size_type;
typedef typename heap_base_maker::compare_argument value_compare;
typedef typename heap_base_maker::allocator_argument allocator_type;
struct ordered_iterator_dispatcher
{
static size_type max_index(const d_ary_heap * heap)
{
return heap->q_.size() - 1;
}
static bool is_leaf(const d_ary_heap * heap, size_type index)
{
return !heap->not_leaf(index);
}
static std::pair<size_type, size_type> get_child_nodes(const d_ary_heap * heap, size_type index)
{
BOOST_HEAP_ASSERT(!is_leaf(heap, index));
return std::make_pair(d_ary_heap::first_child_index(index),
heap->last_child_index(index));
}
static internal_type const & get_internal_value(const d_ary_heap * heap, size_type index)
{
return heap->q_[index];
}
static value_type const & get_value(internal_type const & arg)
{
return super_t::get_value(arg);
}
};
typedef detail::ordered_adaptor_iterator<const value_type,
internal_type,
d_ary_heap,
allocator_type,
typename super_t::internal_compare,
ordered_iterator_dispatcher
> ordered_iterator;
typedef detail::stable_heap_iterator<const value_type, container_iterator, super_t> iterator;
typedef iterator const_iterator;
typedef void * handle_type;
};
typedef typename implementation_defined::ordered_iterator_dispatcher ordered_iterator_dispatcher;
public:
typedef T value_type;
typedef typename implementation_defined::size_type size_type;
typedef typename implementation_defined::difference_type difference_type;
typedef typename implementation_defined::value_compare value_compare;
typedef typename implementation_defined::allocator_type allocator_type;
typedef typename implementation_defined::reference reference;
typedef typename implementation_defined::const_reference const_reference;
typedef typename implementation_defined::pointer pointer;
typedef typename implementation_defined::const_pointer const_pointer;
typedef typename implementation_defined::iterator iterator;
typedef typename implementation_defined::const_iterator const_iterator;
typedef typename implementation_defined::ordered_iterator ordered_iterator;
typedef typename implementation_defined::handle_type handle_type;
static const bool is_stable = extract_stable<BoundArgs>::value;
explicit d_ary_heap(value_compare const & cmp = value_compare()):
super_t(cmp)
{}
d_ary_heap(d_ary_heap const & rhs):
super_t(rhs), q_(rhs.q_)
{}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
d_ary_heap(d_ary_heap && rhs):
super_t(std::move(rhs)), q_(std::move(rhs.q_))
{}
d_ary_heap & operator=(d_ary_heap && rhs)
{
super_t::operator=(std::move(rhs));
q_ = std::move(rhs.q_);
return *this;
}
#endif
d_ary_heap & operator=(d_ary_heap const & rhs)
{
static_cast<super_t&>(*this) = static_cast<super_t const &>(rhs);
q_ = rhs.q_;
return *this;
}
bool empty(void) const
{
return q_.empty();
}
size_type size(void) const
{
return q_.size();
}
size_type max_size(void) const
{
return q_.max_size();
}
void clear(void)
{
q_.clear();
}
allocator_type get_allocator(void) const
{
return q_.get_allocator();
}
value_type const & top(void) const
{
BOOST_ASSERT(!empty());
return super_t::get_value(q_.front());
}
void push(value_type const & v)
{
q_.push_back(super_t::make_node(v));
reset_index(size() - 1, size() - 1);
siftup(q_.size() - 1);
}
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class... Args>
void emplace(Args&&... args)
{
q_.emplace_back(super_t::make_node(std::forward<Args>(args)...));
reset_index(size() - 1, size() - 1);
siftup(q_.size() - 1);
}
#endif
void pop(void)
{
BOOST_ASSERT(!empty());
std::swap(q_.front(), q_.back());
q_.pop_back();
if (q_.empty())
return;
reset_index(0, 0);
siftdown(0);
}
void swap(d_ary_heap & rhs)
{
super_t::swap(rhs);
q_.swap(rhs.q_);
}
iterator begin(void) const
{
return iterator(q_.begin());
}
iterator end(void) const
{
return iterator(q_.end());
}
ordered_iterator ordered_begin(void) const
{
return ordered_iterator(0, this, super_t::get_internal_cmp());
}
ordered_iterator ordered_end(void) const
{
return ordered_iterator(size(), this, super_t::get_internal_cmp());
}
void reserve (size_type element_count)
{
q_.reserve(element_count);
}
value_compare const & value_comp(void) const
{
return super_t::value_comp();
}
private:
void reset_index(size_type index, size_type new_index)
{
BOOST_HEAP_ASSERT(index < q_.size());
index_updater::run(q_[index], new_index);
}
void siftdown(size_type index)
{
while (not_leaf(index)) {
size_type max_child_index = top_child_index(index);
if (!super_t::operator()(q_[max_child_index], q_[index])) {
reset_index(index, max_child_index);
reset_index(max_child_index, index);
std::swap(q_[max_child_index], q_[index]);
index = max_child_index;
}
else
return;
}
}
/* returns new index */
void siftup(size_type index)
{
while (index != 0) {
size_type parent = parent_index(index);
if (super_t::operator()(q_[parent], q_[index])) {
reset_index(index, parent);
reset_index(parent, index);
std::swap(q_[parent], q_[index]);
index = parent;
}
else
return;
}
}
bool not_leaf(size_type index) const
{
const size_t first_child = first_child_index(index);
return first_child < q_.size();
}
size_type top_child_index(size_type index) const
{
// invariant: index is not a leaf, so the iterator range is not empty
const size_t first_index = first_child_index(index);
typedef typename container_type::const_iterator container_iterator;
const container_iterator first_child = q_.begin() + first_index;
const container_iterator end = q_.end();
const size_type max_elements = std::distance(first_child, end);
const container_iterator last_child = (max_elements > D) ? first_child + D
: end;
const container_iterator min_element = std::max_element(first_child, last_child, static_cast<super_t const &>(*this));
return min_element - q_.begin();
}
static size_type parent_index(size_type index)
{
return (index - 1) / D;
}
static size_type first_child_index(size_type index)
{
return index * D + 1;
}
size_type last_child_index(size_type index) const
{
typedef typename container_type::const_iterator container_iterator;
const size_t first_index = first_child_index(index);
const size_type last_index = (std::min)(first_index + D - 1, size() - 1);
return last_index;
}
template<typename U,
typename V,
typename W,
typename X>
struct rebind {
typedef d_ary_heap<U, typename d_ary_heap_signature::bind<boost::heap::stable<heap_base_maker::is_stable>,
boost::heap::stability_counter_type<typename heap_base_maker::stability_counter_type>,
boost::heap::arity<D>,
boost::heap::compare<V>,
boost::heap::allocator<W>
>::type,
X
> other;
};
template <class U> friend class priority_queue_mutable_wrapper;
void update(size_type index)
{
if (index == 0) {
siftdown(index);
return;
}
size_type parent = parent_index(index);
if (super_t::operator()(q_[parent], q_[index]))
siftup(index);
else
siftdown(index);
}
void erase(size_type index)
{
while (index != 0)
{
size_type parent = parent_index(index);
reset_index(index, parent);
reset_index(parent, index);
std::swap(q_[parent], q_[index]);
index = parent;
}
pop();
}
void increase(size_type index)
{
siftup(index);
}
void decrease(size_type index)
{
siftdown(index);
}
};
template <typename T, typename BoundArgs>
struct select_dary_heap
{
static const bool is_mutable = extract_mutable<BoundArgs>::value;
typedef typename mpl::if_c< is_mutable,
priority_queue_mutable_wrapper<d_ary_heap<T, BoundArgs, nop_index_updater > >,
d_ary_heap<T, BoundArgs, nop_index_updater >
>::type type;
};
} /* namespace detail */
/**
* \class d_ary_heap
* \brief d-ary heap class
*
* This class implements an immutable priority queue. Internally, the d-ary heap is represented
* as dynamically sized array (std::vector), that directly stores the values.
*
* The template parameter T is the type to be managed by the container.
* The user can specify additional options and if no options are provided default options are used.
*
* The container supports the following options:
* - \c boost::heap::arity<>, required
* - \c boost::heap::compare<>, defaults to \c compare<std::less<T> >
* - \c boost::heap::stable<>, defaults to \c stable<false>
* - \c boost::heap::stability_counter_type<>, defaults to \c stability_counter_type<boost::uintmax_t>
* - \c boost::heap::allocator<>, defaults to \c allocator<std::allocator<T> >
* - \c boost::heap::mutable_<>, defaults to \c mutable_<false>
*
*/
#ifdef BOOST_DOXYGEN_INVOKED
template<class T, class ...Options>
#else
template <typename T,
class A0 = boost::parameter::void_,
class A1 = boost::parameter::void_,
class A2 = boost::parameter::void_,
class A3 = boost::parameter::void_,
class A4 = boost::parameter::void_,
class A5 = boost::parameter::void_
>
#endif
class d_ary_heap:
public detail::select_dary_heap<T, typename detail::d_ary_heap_signature::bind<A0, A1, A2, A3, A4, A5>::type>::type
{
typedef typename detail::d_ary_heap_signature::bind<A0, A1, A2, A3, A4, A5>::type bound_args;
typedef typename detail::select_dary_heap<T, bound_args>::type super_t;
template <typename Heap1, typename Heap2>
friend struct heap_merge_emulate;
#ifndef BOOST_DOXYGEN_INVOKED
static const bool is_mutable = detail::extract_mutable<bound_args>::value;
#define BOOST_HEAP_TYPEDEF_FROM_SUPER_T(NAME) \
typedef typename super_t::NAME NAME;
struct implementation_defined
{
BOOST_HEAP_TYPEDEF_FROM_SUPER_T(size_type)
BOOST_HEAP_TYPEDEF_FROM_SUPER_T(difference_type)
BOOST_HEAP_TYPEDEF_FROM_SUPER_T(value_compare)
BOOST_HEAP_TYPEDEF_FROM_SUPER_T(allocator_type)
BOOST_HEAP_TYPEDEF_FROM_SUPER_T(reference)
BOOST_HEAP_TYPEDEF_FROM_SUPER_T(const_reference)
BOOST_HEAP_TYPEDEF_FROM_SUPER_T(pointer)
BOOST_HEAP_TYPEDEF_FROM_SUPER_T(const_pointer)
BOOST_HEAP_TYPEDEF_FROM_SUPER_T(iterator)
BOOST_HEAP_TYPEDEF_FROM_SUPER_T(const_iterator)
BOOST_HEAP_TYPEDEF_FROM_SUPER_T(ordered_iterator)
BOOST_HEAP_TYPEDEF_FROM_SUPER_T(handle_type)
};
#undef BOOST_HEAP_TYPEDEF_FROM_SUPER_T
#endif
public:
static const bool constant_time_size = true;
static const bool has_ordered_iterators = true;
static const bool is_mergable = false;
static const bool has_reserve = true;
static const bool is_stable = super_t::is_stable;
typedef T value_type;
typedef typename implementation_defined::size_type size_type;
typedef typename implementation_defined::difference_type difference_type;
typedef typename implementation_defined::value_compare value_compare;
typedef typename implementation_defined::allocator_type allocator_type;
typedef typename implementation_defined::reference reference;
typedef typename implementation_defined::const_reference const_reference;
typedef typename implementation_defined::pointer pointer;
typedef typename implementation_defined::const_pointer const_pointer;
/// \copydoc boost::heap::priority_queue::iterator
typedef typename implementation_defined::iterator iterator;
typedef typename implementation_defined::const_iterator const_iterator;
typedef typename implementation_defined::ordered_iterator ordered_iterator;
typedef typename implementation_defined::handle_type handle_type;
/// \copydoc boost::heap::priority_queue::priority_queue(value_compare const &)
explicit d_ary_heap(value_compare const & cmp = value_compare()):
super_t(cmp)
{}
/// \copydoc boost::heap::priority_queue::priority_queue(priority_queue const &)
d_ary_heap(d_ary_heap const & rhs):
super_t(rhs)
{}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
/// \copydoc boost::heap::priority_queue::priority_queue(priority_queue &&)
d_ary_heap(d_ary_heap && rhs):
super_t(std::move(rhs))
{}
/// \copydoc boost::heap::priority_queue::operator=(priority_queue &&)
d_ary_heap & operator=(d_ary_heap && rhs)
{
super_t::operator=(std::move(rhs));
return *this;
}
#endif
/// \copydoc boost::heap::priority_queue::operator=(priority_queue const &)
d_ary_heap & operator=(d_ary_heap const & rhs)
{
super_t::operator=(rhs);
return *this;
}
/// \copydoc boost::heap::priority_queue::empty
bool empty(void) const
{
return super_t::empty();
}
/// \copydoc boost::heap::priority_queue::size
size_type size(void) const
{
return super_t::size();
}
/// \copydoc boost::heap::priority_queue::max_size
size_type max_size(void) const
{
return super_t::max_size();
}
/// \copydoc boost::heap::priority_queue::clear
void clear(void)
{
super_t::clear();
}
/// \copydoc boost::heap::priority_queue::get_allocator
allocator_type get_allocator(void) const
{
return super_t::get_allocator();
}
/// \copydoc boost::heap::priority_queue::top
value_type const & top(void) const
{
return super_t::top();
}
/// \copydoc boost::heap::priority_queue::push
typename mpl::if_c<is_mutable, handle_type, void>::type push(value_type const & v)
{
return super_t::push(v);
}
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
/// \copydoc boost::heap::priority_queue::emplace
template <class... Args>
typename mpl::if_c<is_mutable, handle_type, void>::type emplace(Args&&... args)
{
return super_t::emplace(std::forward<Args>(args)...);
}
#endif
/// \copydoc boost::heap::priority_queue::operator<(HeapType const & rhs) const
template <typename HeapType>
bool operator<(HeapType const & rhs) const
{
return detail::heap_compare(*this, rhs);
}
/// \copydoc boost::heap::priority_queue::operator>(HeapType const & rhs) const
template <typename HeapType>
bool operator>(HeapType const & rhs) const
{
return detail::heap_compare(rhs, *this);
}
/// \copydoc boost::heap::priority_queue::operator>=(HeapType const & rhs) const
template <typename HeapType>
bool operator>=(HeapType const & rhs) const
{
return !operator<(rhs);
}
/// \copydoc boost::heap::priority_queue::operator<=(HeapType const & rhs) const
template <typename HeapType>
bool operator<=(HeapType const & rhs) const
{
return !operator>(rhs);
}
/// \copydoc boost::heap::priority_queue::operator==(HeapType const & rhs) const
template <typename HeapType>
bool operator==(HeapType const & rhs) const
{
return detail::heap_equality(*this, rhs);
}
/// \copydoc boost::heap::priority_queue::operator!=(HeapType const & rhs) const
template <typename HeapType>
bool operator!=(HeapType const & rhs) const
{
return !(*this == rhs);
}
/**
* \b Effects: Assigns \c v to the element handled by \c handle & updates the priority queue.
*
* \b Complexity: Logarithmic.
*
* \b Requirement: data structure must be configured as mutable
* */
void update(handle_type handle, const_reference v)
{
BOOST_STATIC_ASSERT(is_mutable);
super_t::update(handle, v);
}
/**
* \b Effects: Updates the heap after the element handled by \c handle has been changed.
*
* \b Complexity: Logarithmic.
*
* \b Note: If this is not called, after a handle has been updated, the behavior of the data structure is undefined!
*
* \b Requirement: data structure must be configured as mutable
* */
void update(handle_type handle)
{
BOOST_STATIC_ASSERT(is_mutable);
super_t::update(handle);
}
/**
* \b Effects: Assigns \c v to the element handled by \c handle & updates the priority queue.
*
* \b Complexity: Logarithmic.
*
* \b Note: The new value is expected to be greater than the current one
*
* \b Requirement: data structure must be configured as mutable
* */
void increase(handle_type handle, const_reference v)
{
BOOST_STATIC_ASSERT(is_mutable);
super_t::increase(handle, v);
}
/**
* \b Effects: Updates the heap after the element handled by \c handle has been changed.
*
* \b Complexity: Logarithmic.
*
* \b Note: The new value is expected to be greater than the current one. If this is not called, after a handle has been updated, the behavior of the data structure is undefined!
*
* \b Requirement: data structure must be configured as mutable
* */
void increase(handle_type handle)
{
BOOST_STATIC_ASSERT(is_mutable);
super_t::increase(handle);
}
/**
* \b Effects: Assigns \c v to the element handled by \c handle & updates the priority queue.
*
* \b Complexity: Logarithmic.
*
* \b Note: The new value is expected to be less than the current one
*
* \b Requirement: data structure must be configured as mutable
* */
void decrease(handle_type handle, const_reference v)
{
BOOST_STATIC_ASSERT(is_mutable);
super_t::decrease(handle, v);
}
/**
* \b Effects: Updates the heap after the element handled by \c handle has been changed.
*
* \b Complexity: Logarithmic.
*
* \b Note: The new value is expected to be less than the current one. If this is not called, after a handle has been updated, the behavior of the data structure is undefined!
*
* \b Requirement: data structure must be configured as mutable
* */
void decrease(handle_type handle)
{
BOOST_STATIC_ASSERT(is_mutable);
super_t::decrease(handle);
}
/**
* \b Effects: Removes the element handled by \c handle from the priority_queue.
*
* \b Complexity: Logarithmic.
*
* \b Requirement: data structure must be configured as mutable
* */
void erase(handle_type handle)
{
BOOST_STATIC_ASSERT(is_mutable);
super_t::erase(handle);
}
/**
* \b Effects: Casts an iterator to a node handle.
*
* \b Complexity: Constant.
*
* \b Requirement: data structure must be configured as mutable
* */
static handle_type s_handle_from_iterator(iterator const & it)
{
BOOST_STATIC_ASSERT(is_mutable);
return super_t::s_handle_from_iterator(it);
}
/// \copydoc boost::heap::priority_queue::pop
void pop(void)
{
super_t::pop();
}
/// \copydoc boost::heap::priority_queue::swap
void swap(d_ary_heap & rhs)
{
super_t::swap(rhs);
}
/// \copydoc boost::heap::priority_queue::begin
const_iterator begin(void) const
{
return super_t::begin();
}
/// \copydoc boost::heap::priority_queue::begin
iterator begin(void)
{
return super_t::begin();
}
/// \copydoc boost::heap::priority_queue::end
iterator end(void)
{
return super_t::end();
}
/// \copydoc boost::heap::priority_queue::end
const_iterator end(void) const
{
return super_t::end();
}
/// \copydoc boost::heap::fibonacci_heap::ordered_begin
ordered_iterator ordered_begin(void) const
{
return super_t::ordered_begin();
}
/// \copydoc boost::heap::fibonacci_heap::ordered_end
ordered_iterator ordered_end(void) const
{
return super_t::ordered_end();
}
/// \copydoc boost::heap::priority_queue::reserve
void reserve (size_type element_count)
{
super_t::reserve(element_count);
}
/// \copydoc boost::heap::priority_queue::value_comp
value_compare const & value_comp(void) const
{
return super_t::value_comp();
}
};
} /* namespace heap */
} /* namespace boost */
#undef BOOST_HEAP_ASSERT
#endif /* BOOST_HEAP_D_ARY_HEAP_HPP */

View File

@@ -0,0 +1,245 @@
// boost heap: heap node helper classes
//
// Copyright (C) 2010 Tim Blechmann
//
// 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_HEAP_DETAIL_HEAP_COMPARISON_HPP
#define BOOST_HEAP_DETAIL_HEAP_COMPARISON_HPP
#include <boost/assert.hpp>
#include <boost/static_assert.hpp>
#include <boost/concept/assert.hpp>
#include <boost/heap/heap_concepts.hpp>
#ifdef BOOST_HEAP_SANITYCHECKS
#define BOOST_HEAP_ASSERT BOOST_ASSERT
#else
#define BOOST_HEAP_ASSERT(expression)
#endif
namespace boost {
namespace heap {
namespace detail {
template <typename Heap1, typename Heap2>
bool value_equality(Heap1 const & lhs, Heap2 const & rhs,
typename Heap1::value_type lval, typename Heap2::value_type rval)
{
typename Heap1::value_compare const & cmp = lhs.value_comp();
bool ret = !(cmp(lval, rval)) && !(cmp(rval, lval));
// if this assertion is triggered, the value_compare objects of lhs and rhs return different values
BOOST_ASSERT((ret == (!(rhs.value_comp()(lval, rval)) && !(rhs.value_comp()(rval, lval)))));
return ret;
}
template <typename Heap1, typename Heap2>
bool value_compare(Heap1 const & lhs, Heap2 const & rhs,
typename Heap1::value_type lval, typename Heap2::value_type rval)
{
typename Heap1::value_compare const & cmp = lhs.value_comp();
bool ret = cmp(lval, rval);
// if this assertion is triggered, the value_compare objects of lhs and rhs return different values
BOOST_ASSERT((ret == rhs.value_comp()(lval, rval)));
return ret;
}
struct heap_equivalence_copy
{
template <typename Heap1, typename Heap2>
bool operator()(Heap1 const & lhs, Heap2 const & rhs)
{
BOOST_CONCEPT_ASSERT((boost::heap::PriorityQueue<Heap1>));
BOOST_CONCEPT_ASSERT((boost::heap::PriorityQueue<Heap2>));
// if this assertion is triggered, the value_compare types are incompatible
BOOST_STATIC_ASSERT((boost::is_same<typename Heap1::value_compare, typename Heap2::value_compare>::value));
if (Heap1::constant_time_size && Heap2::constant_time_size)
if (lhs.size() != rhs.size())
return false;
if (lhs.empty() && rhs.empty())
return true;
Heap1 lhs_copy(lhs);
Heap2 rhs_copy(rhs);
while (true) {
if (!value_equality(lhs_copy, rhs_copy, lhs_copy.top(), rhs_copy.top()))
return false;
lhs_copy.pop();
rhs_copy.pop();
if (lhs_copy.empty() && rhs_copy.empty())
return true;
if (lhs_copy.empty())
return false;
if (rhs_copy.empty())
return false;
}
}
};
struct heap_equivalence_iteration
{
template <typename Heap1, typename Heap2>
bool operator()(Heap1 const & lhs, Heap2 const & rhs)
{
BOOST_CONCEPT_ASSERT((boost::heap::PriorityQueue<Heap1>));
BOOST_CONCEPT_ASSERT((boost::heap::PriorityQueue<Heap2>));
// if this assertion is triggered, the value_compare types are incompatible
BOOST_STATIC_ASSERT((boost::is_same<typename Heap1::value_compare, typename Heap2::value_compare>::value));
if (Heap1::constant_time_size && Heap2::constant_time_size)
if (lhs.size() != rhs.size())
return false;
if (lhs.empty() && rhs.empty())
return true;
typename Heap1::ordered_iterator it1 = lhs.ordered_begin();
typename Heap1::ordered_iterator it1_end = lhs.ordered_end();
typename Heap1::ordered_iterator it2 = rhs.ordered_begin();
typename Heap1::ordered_iterator it2_end = rhs.ordered_end();
while (true) {
if (!value_equality(lhs, rhs, *it1, *it2))
return false;
++it1;
++it2;
if (it1 == it1_end && it2 == it2_end)
return true;
if (it1 == it1_end || it2 == it2_end)
return false;
}
}
};
template <typename Heap1,
typename Heap2
>
bool heap_equality(Heap1 const & lhs, Heap2 const & rhs)
{
const bool use_ordered_iterators = Heap1::has_ordered_iterators && Heap2::has_ordered_iterators;
typedef typename boost::mpl::if_c<use_ordered_iterators,
heap_equivalence_iteration,
heap_equivalence_copy
>::type equivalence_check;
equivalence_check eq_check;
return eq_check(lhs, rhs);
}
struct heap_compare_iteration
{
template <typename Heap1,
typename Heap2
>
bool operator()(Heap1 const & lhs, Heap2 const & rhs)
{
typename Heap1::size_type left_size = lhs.size();
typename Heap2::size_type right_size = rhs.size();
if (left_size < right_size)
return true;
if (left_size > right_size)
return false;
typename Heap1::ordered_iterator it1 = lhs.ordered_begin();
typename Heap1::ordered_iterator it1_end = lhs.ordered_end();
typename Heap1::ordered_iterator it2 = rhs.ordered_begin();
typename Heap1::ordered_iterator it2_end = rhs.ordered_end();
while (true) {
if (value_compare(lhs, rhs, *it1, *it2))
return true;
if (value_compare(lhs, rhs, *it2, *it1))
return false;
++it1;
++it2;
if (it1 == it1_end && it2 == it2_end)
return true;
if (it1 == it1_end || it2 == it2_end)
return false;
}
}
};
struct heap_compare_copy
{
template <typename Heap1,
typename Heap2
>
bool operator()(Heap1 const & lhs, Heap2 const & rhs)
{
typename Heap1::size_type left_size = lhs.size();
typename Heap2::size_type right_size = rhs.size();
if (left_size < right_size)
return true;
if (left_size > right_size)
return false;
Heap1 lhs_copy(lhs);
Heap2 rhs_copy(rhs);
while (true) {
if (value_compare(lhs_copy, rhs_copy, lhs_copy.top(), rhs_copy.top()))
return true;
if (value_compare(lhs_copy, rhs_copy, rhs_copy.top(), lhs_copy.top()))
return false;
lhs_copy.pop();
rhs_copy.pop();
if (lhs_copy.empty() && rhs_copy.empty())
return false;
}
}
};
template <typename Heap1,
typename Heap2
>
bool heap_compare(Heap1 const & lhs, Heap2 const & rhs)
{
const bool use_ordered_iterators = Heap1::has_ordered_iterators && Heap2::has_ordered_iterators;
typedef typename boost::mpl::if_c<use_ordered_iterators,
heap_compare_iteration,
heap_compare_copy
>::type compare_check;
compare_check check_object;
return check_object(lhs, rhs);
}
} /* namespace detail */
} /* namespace heap */
} /* namespace boost */
#undef BOOST_HEAP_ASSERT
#endif // BOOST_HEAP_DETAIL_HEAP_COMPARISON_HPP

View File

@@ -0,0 +1,366 @@
// boost heap: heap node helper classes
//
// Copyright (C) 2010 Tim Blechmann
//
// 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_HEAP_DETAIL_HEAP_NODE_HPP
#define BOOST_HEAP_DETAIL_HEAP_NODE_HPP
#include <boost/assert.hpp>
#include <boost/static_assert.hpp>
#include <boost/intrusive/list.hpp>
#include <boost/mpl/if.hpp>
#ifdef BOOST_HEAP_SANITYCHECKS
#define BOOST_HEAP_ASSERT BOOST_ASSERT
#else
#define BOOST_HEAP_ASSERT(expression)
#endif
namespace boost {
namespace heap {
namespace detail {
namespace bi = boost::intrusive;
namespace mpl = boost::mpl;
template <bool auto_unlink = false>
struct heap_node_base:
bi::list_base_hook<typename mpl::if_c<auto_unlink,
bi::link_mode<bi::auto_unlink>,
bi::link_mode<bi::safe_link>
>::type
>
{};
typedef bi::list<heap_node_base<false> > heap_node_list;
struct nop_disposer
{
template <typename T>
void operator()(T * n)
{
BOOST_HEAP_ASSERT(false);
}
};
template <typename Node, typename HeapBase>
bool is_heap(const Node * n, typename HeapBase::value_compare const & cmp)
{
for (typename Node::const_child_iterator it = n->children.begin(); it != n->children.end(); ++it) {
Node const & this_node = static_cast<Node const &>(*it);
const Node * child = static_cast<const Node*>(&this_node);
if (cmp(HeapBase::get_value(n->value), HeapBase::get_value(child->value)) ||
!is_heap<Node, HeapBase>(child, cmp))
return false;
}
return true;
}
template <typename Node>
std::size_t count_nodes(const Node * n);
template <typename Node, typename List>
std::size_t count_list_nodes(List const & node_list)
{
std::size_t ret = 0;
for (typename List::const_iterator it = node_list.begin(); it != node_list.end(); ++it) {
const Node * child = static_cast<const Node*>(&*it);
ret += count_nodes<Node>(child);
}
return ret;
}
template <typename Node>
std::size_t count_nodes(const Node * n)
{
return 1 + count_list_nodes<Node, typename Node::child_list>(n->children);
}
/* node cloner
*
* Requires `Clone Constructor':
* template <typename Alloc>
* Node::Node(Node const &, Alloc &)
*
* template <typename Alloc>
* Node::Node(Node const &, Alloc &, Node * parent)
*
* */
template <typename Node,
typename NodeBase,
typename Alloc>
struct node_cloner
{
node_cloner(Alloc & allocator):
allocator(allocator)
{}
Node * operator() (NodeBase const & node)
{
Node * ret = allocator.allocate(1);
new (ret) Node(static_cast<Node const &>(node), allocator);
return ret;
}
Node * operator() (NodeBase const & node, Node * parent)
{
Node * ret = allocator.allocate(1);
new (ret) Node(static_cast<Node const &>(node), allocator, parent);
return ret;
}
private:
Alloc & allocator;
};
/* node disposer
*
* Requirements:
* Node::clear_subtree(Alloc &) clears the subtree via allocator
*
* */
template <typename Node,
typename NodeBase,
typename Alloc>
struct node_disposer
{
typedef typename Alloc::pointer node_pointer;
node_disposer(Alloc & alloc):
alloc_(alloc)
{}
void operator()(NodeBase * base)
{
node_pointer n = static_cast<node_pointer>(base);
n->clear_subtree(alloc_);
alloc_.deallocate(n, 1);
}
Alloc & alloc_;
};
template <typename ValueType,
bool constant_time_child_size = true
>
struct heap_node:
heap_node_base<!constant_time_child_size>
{
typedef heap_node_base<!constant_time_child_size> node_base;
public:
typedef ValueType value_type;
typedef bi::list<node_base,
bi::constant_time_size<constant_time_child_size> > child_list;
typedef typename child_list::iterator child_iterator;
typedef typename child_list::const_iterator const_child_iterator;
typedef typename child_list::size_type size_type;
heap_node(ValueType const & v):
value(v)
{}
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class... Args>
heap_node(Args&&... args):
value(std::forward<Args>(args)...)
{}
#endif
/* protected: */
heap_node(heap_node const & rhs):
value(rhs.value)
{
/* we don't copy the child list, but clone it later */
}
public:
template <typename Alloc>
heap_node (heap_node const & rhs, Alloc & allocator):
value(rhs.value)
{
children.clone_from(rhs.children, node_cloner<heap_node, node_base, Alloc>(allocator), nop_disposer());
}
size_type child_count(void) const
{
BOOST_STATIC_ASSERT(constant_time_child_size);
return children.size();
}
void add_child(heap_node * n)
{
children.push_back(*n);
}
template <typename Alloc>
void clear_subtree(Alloc & alloc)
{
children.clear_and_dispose(node_disposer<heap_node, node_base, Alloc>(alloc));
}
void swap_children(heap_node * rhs)
{
children.swap(rhs->children);
}
ValueType value;
child_list children;
};
template <typename value_type>
struct parent_pointing_heap_node:
heap_node<value_type>
{
typedef heap_node<value_type> super_t;
parent_pointing_heap_node(value_type const & v):
super_t(v), parent(NULL)
{}
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class... Args>
parent_pointing_heap_node(Args&&... args):
super_t(std::forward<Args>(args)...), parent(NULL)
{}
#endif
template <typename Alloc>
struct node_cloner
{
node_cloner(Alloc & allocator, parent_pointing_heap_node * parent):
allocator(allocator), parent_(parent)
{}
parent_pointing_heap_node * operator() (typename super_t::node_base const & node)
{
parent_pointing_heap_node * ret = allocator.allocate(1);
new (ret) parent_pointing_heap_node(static_cast<parent_pointing_heap_node const &>(node), allocator, parent_);
return ret;
}
private:
Alloc & allocator;
parent_pointing_heap_node * parent_;
};
template <typename Alloc>
parent_pointing_heap_node (parent_pointing_heap_node const & rhs, Alloc & allocator, parent_pointing_heap_node * parent):
super_t(static_cast<super_t const &>(rhs)), parent(parent)
{
super_t::children.clone_from(rhs.children, node_cloner<Alloc>(allocator, this), nop_disposer());
}
void update_children(void)
{
typedef heap_node_list::iterator node_list_iterator;
for (node_list_iterator it = super_t::children.begin(); it != super_t::children.end(); ++it) {
parent_pointing_heap_node * child = static_cast<parent_pointing_heap_node*>(&*it);
child->parent = this;
}
}
void remove_from_parent(void)
{
BOOST_HEAP_ASSERT(parent);
parent->children.erase(heap_node_list::s_iterator_to(*this));
parent = NULL;
}
void add_child(parent_pointing_heap_node * n)
{
BOOST_HEAP_ASSERT(n->parent == NULL);
n->parent = this;
super_t::add_child(n);
}
parent_pointing_heap_node * get_parent(void)
{
return parent;
}
const parent_pointing_heap_node * get_parent(void) const
{
return parent;
}
parent_pointing_heap_node * parent;
};
template <typename value_type>
struct marked_heap_node:
parent_pointing_heap_node<value_type>
{
typedef parent_pointing_heap_node<value_type> super_t;
marked_heap_node(value_type const & v):
super_t(v), mark(false)
{}
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class... Args>
marked_heap_node(Args&&... args):
super_t(std::forward<Args>(args)...), mark(false)
{}
#endif
marked_heap_node * get_parent(void)
{
return static_cast<marked_heap_node*>(super_t::parent);
}
const marked_heap_node * get_parent(void) const
{
return static_cast<marked_heap_node*>(super_t::parent);
}
bool mark;
};
template <typename Node>
struct cmp_by_degree
{
template <typename NodeBase>
bool operator()(NodeBase const & left,
NodeBase const & right)
{
return static_cast<const Node*>(&left)->child_count() < static_cast<const Node*>(&right)->child_count();
}
};
template <typename List, typename Node, typename Cmp>
Node * find_max_child(List const & list, Cmp const & cmp)
{
BOOST_HEAP_ASSERT(!list.empty());
const Node * ret = static_cast<const Node *> (&list.front());
for (typename List::const_iterator it = list.begin(); it != list.end(); ++it) {
const Node * current = static_cast<const Node *> (&*it);
if (cmp(ret->value, current->value))
ret = current;
}
return const_cast<Node*>(ret);
}
} /* namespace detail */
} /* namespace heap */
} /* namespace boost */
#undef BOOST_HEAP_ASSERT
#endif /* BOOST_HEAP_DETAIL_HEAP_NODE_HPP */

View File

@@ -0,0 +1,64 @@
// boost heap: integer log2
//
// Copyright (C) 2010 Tim Blechmann
//
// 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_HEAP_DETAIL_ILOG2_HPP
#define BOOST_HEAP_DETAIL_ILOG2_HPP
#include <string> // std::size_t
namespace boost {
namespace heap {
namespace detail {
template <typename IntType>
struct log2
{
IntType operator()(IntType value)
{
IntType l = 0;
while( (value >> l) > 1 )
++l;
return l;
}
};
#ifdef __GNUC__
template<>
struct log2<unsigned int>
{
unsigned int operator()(unsigned int value)
{
return sizeof(unsigned int)*8 - __builtin_clz(value - 1);
}
};
template<>
struct log2<unsigned long>
{
unsigned long operator()(unsigned long value)
{
return sizeof(unsigned long)*8 - __builtin_clzl(value - 1);
}
};
#endif
} /* namespace detail */
template <typename IntType>
IntType log2(IntType value)
{
detail::log2<IntType> fn;
return fn(value);
}
} /* namespace heap */
} /* namespace boost */
#endif /* BOOST_HEAP_DETAIL_ILOG2_HPP */

View File

@@ -0,0 +1,529 @@
// boost heap
//
// Copyright (C) 2010 Tim Blechmann
//
// 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_HEAP_DETAIL_MUTABLE_HEAP_HPP
#define BOOST_HEAP_DETAIL_MUTABLE_HEAP_HPP
/*! \file
* INTERNAL ONLY
*/
#include <list>
#include <utility>
#include <boost/noncopyable.hpp>
#include <boost/iterator/iterator_adaptor.hpp>
#include <boost/heap/detail/ordered_adaptor_iterator.hpp>
namespace boost {
namespace heap {
namespace detail {
/* wrapper for a mutable heap container adaptors
*
* this wrapper introduces an additional indirection. the heap is not constructed from objects,
* but instead from std::list iterators. this way, the mutability is achieved
*
*/
template <typename PriorityQueueType>
class priority_queue_mutable_wrapper
{
public:
typedef typename PriorityQueueType::value_type value_type;
typedef typename PriorityQueueType::size_type size_type;
typedef typename PriorityQueueType::value_compare value_compare;
typedef typename PriorityQueueType::allocator_type allocator_type;
typedef typename PriorityQueueType::reference reference;
typedef typename PriorityQueueType::const_reference const_reference;
typedef typename PriorityQueueType::pointer pointer;
typedef typename PriorityQueueType::const_pointer const_pointer;
static const bool is_stable = PriorityQueueType::is_stable;
private:
typedef std::pair<value_type, size_type> node_type;
typedef std::list<node_type, typename allocator_type::template rebind<node_type>::other> object_list;
typedef typename object_list::iterator list_iterator;
typedef typename object_list::const_iterator const_list_iterator;
template <typename Heap1, typename Heap2>
friend struct heap_merge_emulate;
typedef typename PriorityQueueType::super_t::stability_counter_type stability_counter_type;
stability_counter_type get_stability_count(void) const
{
return q_.get_stability_count();
}
void set_stability_count(stability_counter_type new_count)
{
q_.set_stability_count(new_count);
}
struct index_updater
{
template <typename It>
static void run(It & it, size_type new_index)
{
q_type::get_value(it)->second = new_index;
}
};
public:
struct handle_type
{
value_type & operator*() const
{
return iterator->first;
}
handle_type (void)
{}
handle_type(handle_type const & rhs):
iterator(rhs.iterator)
{}
private:
explicit handle_type(list_iterator const & it):
iterator(it)
{}
list_iterator iterator;
friend class priority_queue_mutable_wrapper;
};
private:
struct indirect_cmp:
public value_compare
{
indirect_cmp(value_compare const & cmp = value_compare()):
value_compare(cmp)
{}
bool operator()(const_list_iterator const & lhs, const_list_iterator const & rhs) const
{
return value_compare::operator()(lhs->first, rhs->first);
}
};
typedef typename PriorityQueueType::template rebind<list_iterator,
indirect_cmp,
allocator_type, index_updater >::other q_type;
protected:
q_type q_;
object_list objects;
protected:
priority_queue_mutable_wrapper(value_compare const & cmp = value_compare()):
q_(cmp)
{}
priority_queue_mutable_wrapper(priority_queue_mutable_wrapper const & rhs):
q_(rhs.q_), objects(rhs.objects)
{
for (typename object_list::iterator it = objects.begin(); it != objects.end(); ++it)
q_.push(it);
}
priority_queue_mutable_wrapper & operator=(priority_queue_mutable_wrapper const & rhs)
{
q_ = rhs.q_;
objects = rhs.objects;
q_.clear();
for (typename object_list::iterator it = objects.begin(); it != objects.end(); ++it)
q_.push(it);
return *this;
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
priority_queue_mutable_wrapper (priority_queue_mutable_wrapper && rhs):
q_(std::move(rhs.q_))
{
/// FIXME: msvc seems to invalidate iterators when moving std::list
std::swap(objects, rhs.objects);
}
priority_queue_mutable_wrapper & operator=(priority_queue_mutable_wrapper && rhs)
{
q_ = std::move(rhs.q_);
objects.clear();
std::swap(objects, rhs.objects);
return *this;
}
#endif
public:
template <typename iterator_type>
class iterator_base:
public boost::iterator_adaptor<iterator_base<iterator_type>,
iterator_type,
value_type const,
boost::bidirectional_traversal_tag>
{
typedef boost::iterator_adaptor<iterator_base<iterator_type>,
iterator_type,
value_type const,
boost::bidirectional_traversal_tag> super_t;
friend class boost::iterator_core_access;
friend class priority_queue_mutable_wrapper;
iterator_base(void):
super_t(0)
{}
template <typename T>
explicit iterator_base(T const & it):
super_t(it)
{}
value_type const & dereference() const
{
return super_t::base()->first;
}
iterator_type get_list_iterator() const
{
return super_t::base_reference();
}
};
typedef iterator_base<list_iterator> iterator;
typedef iterator_base<const_list_iterator> const_iterator;
typedef typename object_list::difference_type difference_type;
class ordered_iterator:
public boost::iterator_adaptor<ordered_iterator,
const_list_iterator,
value_type const,
boost::forward_traversal_tag
>,
q_type::ordered_iterator_dispatcher
{
typedef boost::iterator_adaptor<ordered_iterator,
const_list_iterator,
value_type const,
boost::forward_traversal_tag
> adaptor_type;
typedef const_list_iterator iterator;
typedef typename q_type::ordered_iterator_dispatcher ordered_iterator_dispatcher;
friend class boost::iterator_core_access;
public:
ordered_iterator(void):
adaptor_type(0), unvisited_nodes(indirect_cmp()), q_(NULL)
{}
ordered_iterator(const priority_queue_mutable_wrapper * q, indirect_cmp const & cmp):
adaptor_type(0), unvisited_nodes(cmp), q_(q)
{}
ordered_iterator(const_list_iterator it, const priority_queue_mutable_wrapper * q, indirect_cmp const & cmp):
adaptor_type(it), unvisited_nodes(cmp), q_(q)
{
if (it != q->objects.end())
discover_nodes(it);
}
bool operator!=(ordered_iterator const & rhs) const
{
return adaptor_type::base() != rhs.base();
}
bool operator==(ordered_iterator const & rhs) const
{
return !operator!=(rhs);
}
private:
void increment(void)
{
if (unvisited_nodes.empty())
adaptor_type::base_reference() = q_->objects.end();
else {
iterator next = unvisited_nodes.top();
unvisited_nodes.pop();
discover_nodes(next);
adaptor_type::base_reference() = next;
}
}
value_type const & dereference() const
{
return adaptor_type::base()->first;
}
void discover_nodes(iterator current)
{
size_type current_index = current->second;
const q_type * q = &(q_->q_);
if (ordered_iterator_dispatcher::is_leaf(q, current_index))
return;
std::pair<size_type, size_type> child_range = ordered_iterator_dispatcher::get_child_nodes(q, current_index);
for (size_type i = child_range.first; i <= child_range.second; ++i) {
typename q_type::internal_type const & internal_value_at_index = ordered_iterator_dispatcher::get_internal_value(q, i);
typename q_type::value_type const & value_at_index = q_->q_.get_value(internal_value_at_index);
unvisited_nodes.push(value_at_index);
}
}
std::priority_queue<iterator,
std::vector<iterator, typename allocator_type::template rebind<iterator>::other >,
indirect_cmp
> unvisited_nodes;
const priority_queue_mutable_wrapper * q_;
};
bool empty(void) const
{
return q_.empty();
}
size_type size(void) const
{
return q_.size();
}
size_type max_size(void) const
{
return objects.max_size();
}
void clear(void)
{
q_.clear();
objects.clear();
}
allocator_type get_allocator(void) const
{
return q_.get_allocator();
}
void swap(priority_queue_mutable_wrapper & rhs)
{
objects.swap(rhs.objects);
q_.swap(rhs.q_);
}
const_reference top(void) const
{
BOOST_ASSERT(!empty());
return q_.top()->first;
}
handle_type push(value_type const & v)
{
objects.push_front(std::make_pair(v, 0));
list_iterator ret = objects.begin();
q_.push(ret);
return handle_type(ret);
}
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class... Args>
handle_type emplace(Args&&... args)
{
objects.push_front(std::make_pair(std::forward<Args>(args)..., 0));
list_iterator ret = objects.begin();
q_.push(ret);
return handle_type(ret);
}
#endif
void pop(void)
{
BOOST_ASSERT(!empty());
list_iterator q_top = q_.top();
q_.pop();
objects.erase(q_top);
}
/**
* \b Effects: Merge with priority queue rhs.
*
* \b Complexity: N log(N)
*
* */
void merge(priority_queue_mutable_wrapper const & rhs)
{
q_.reserve(q_.size() + rhs.q_.size());
for (typename object_list::const_iterator it = rhs.objects.begin(); it != rhs.objects.end(); ++it)
push(it->first);
}
/**
* \b Effects: Assigns \c v to the element handled by \c handle & updates the priority queue.
*
* \b Complexity: Logarithmic.
*
* */
void update(handle_type handle, const_reference v)
{
list_iterator it = handle.iterator;
value_type const & current_value = it->first;
value_compare const & cmp = q_.value_comp();
if (cmp(v, current_value))
decrease(handle, v);
else
increase(handle, v);
}
/**
* \b Effects: Updates the heap after the element handled by \c handle has been changed.
*
* \b Complexity: Logarithmic.
*
* \b Note: If this is not called, after a handle has been updated, the behavior of the data structure is undefined!
* */
void update(handle_type handle)
{
list_iterator it = handle.iterator;
size_type index = it->second;
q_.update(index);
}
/**
* \b Effects: Assigns \c v to the element handled by \c handle & updates the priority queue.
*
* \b Complexity: Logarithmic.
*
* \b Note: The new value is expected to be greater than the current one
* */
void increase(handle_type handle, const_reference v)
{
BOOST_ASSERT(!value_compare()(v, handle.iterator->first));
handle.iterator->first = v;
increase(handle);
}
/**
* \b Effects: Updates the heap after the element handled by \c handle has been changed.
*
* \b Complexity: Logarithmic.
*
* \b Note: The new value is expected to be greater than the current one. If this is not called, after a handle has been updated, the behavior of the data structure is undefined!
* */
void increase(handle_type handle)
{
list_iterator it = handle.iterator;
size_type index = it->second;
q_.increase(index);
}
/**
* \b Effects: Assigns \c v to the element handled by \c handle & updates the priority queue.
*
* \b Complexity: Logarithmic.
*
* \b Note: The new value is expected to be less than the current one
* */
void decrease(handle_type handle, const_reference v)
{
BOOST_ASSERT(!value_compare()(handle.iterator->first, v));
handle.iterator->first = v;
decrease(handle);
}
/**
* \b Effects: Updates the heap after the element handled by \c handle has been changed.
*
* \b Complexity: Logarithmic.
*
* \b Note: The new value is expected to be less than the current one. If this is not called, after a handle has been updated, the behavior of the data structure is undefined!
* */
void decrease(handle_type handle)
{
list_iterator it = handle.iterator;
size_type index = it->second;
q_.decrease(index);
}
/**
* \b Effects: Removes the element handled by \c handle from the priority_queue.
*
* \b Complexity: Logarithmic.
* */
void erase(handle_type handle)
{
list_iterator it = handle.iterator;
size_type index = it->second;
q_.erase(index);
objects.erase(it);
}
const_iterator begin(void) const
{
return const_iterator(objects.begin());
}
const_iterator end(void) const
{
return const_iterator(objects.end());
}
iterator begin(void)
{
return iterator(objects.begin());
}
iterator end(void)
{
return iterator(objects.end());
}
ordered_iterator ordered_begin(void) const
{
if (!empty())
return ordered_iterator(q_.top(), this, indirect_cmp(q_.value_comp()));
else
return ordered_end();
}
ordered_iterator ordered_end(void) const
{
return ordered_iterator(objects.end(), this, indirect_cmp(q_.value_comp()));
}
static handle_type s_handle_from_iterator(iterator const & it)
{
return handle_type(it.get_list_iterator());
}
value_compare const & value_comp(void) const
{
return q_.value_comp();
}
void reserve (size_type element_count)
{
q_.reserve(element_count);
}
};
} /* namespace detail */
} /* namespace heap */
} /* namespace boost */
#endif /* BOOST_HEAP_DETAIL_MUTABLE_HEAP_HPP */

View File

@@ -0,0 +1,146 @@
// boost heap: ordered iterator helper classes for container adaptors
//
// Copyright (C) 2011 Tim Blechmann
//
// 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_HEAP_DETAIL_ORDERED_ADAPTOR_ITERATOR_HPP
#define BOOST_HEAP_DETAIL_ORDERED_ADAPTOR_ITERATOR_HPP
#include <cassert>
#include <limits>
#include <boost/assert.hpp>
#include <boost/heap/detail/tree_iterator.hpp>
#include <boost/iterator/iterator_adaptor.hpp>
#include <boost/concept_check.hpp>
namespace boost {
namespace heap {
namespace detail {
/* ordered iterator helper classes for container adaptors
*
* Requirements for Dispatcher:
*
* * static size_type max_index(const ContainerType * heap); // return maximum index
* * static bool is_leaf(const ContainerType * heap, size_type index); // return if index denotes a leaf
* * static std::pair<size_type, size_type> get_child_nodes(const ContainerType * heap, size_type index); // get index range of child nodes
* * static internal_type const & get_internal_value(const ContainerType * heap, size_type index); // get internal value at index
* * static value_type const & get_value(internal_type const & arg) const; // get value_type from internal_type
*
* */
template <typename ValueType,
typename InternalType,
typename ContainerType,
typename Alloc,
typename ValueCompare,
typename Dispatcher
>
class ordered_adaptor_iterator:
public boost::iterator_facade<ordered_adaptor_iterator<ValueType,
InternalType,
ContainerType,
Alloc,
ValueCompare,
Dispatcher>,
ValueType,
boost::forward_traversal_tag
>,
Dispatcher
{
friend class boost::iterator_core_access;
struct compare_by_heap_value:
ValueCompare
{
const ContainerType * container;
compare_by_heap_value (const ContainerType * container, ValueCompare const & cmp):
ValueCompare(cmp), container(container)
{}
bool operator()(size_t lhs, size_t rhs)
{
BOOST_ASSERT(lhs <= Dispatcher::max_index(container));
BOOST_ASSERT(rhs <= Dispatcher::max_index(container));
return ValueCompare::operator()(Dispatcher::get_internal_value(container, lhs),
Dispatcher::get_internal_value(container, rhs));
}
};
const ContainerType * container;
size_t current_index; // current index: special value -1 denotes `end' iterator
public:
ordered_adaptor_iterator(void):
container(NULL), current_index((std::numeric_limits<size_t>::max)()),
unvisited_nodes(compare_by_heap_value(NULL, ValueCompare()))
{}
ordered_adaptor_iterator(const ContainerType * container, ValueCompare const & cmp):
container(container), current_index(container->size()),
unvisited_nodes(compare_by_heap_value(container, ValueCompare()))
{}
ordered_adaptor_iterator(size_t initial_index, const ContainerType * container, ValueCompare const & cmp):
container(container), current_index(initial_index),
unvisited_nodes(compare_by_heap_value(container, cmp))
{
discover_nodes(initial_index);
}
private:
bool equal (ordered_adaptor_iterator const & rhs) const
{
if (current_index != rhs.current_index)
return false;
if (container != rhs.container) // less likely than first check
return false;
return true;
}
void increment(void)
{
if (unvisited_nodes.empty())
current_index = Dispatcher::max_index(container) + 1;
else {
current_index = unvisited_nodes.top();
unvisited_nodes.pop();
discover_nodes(current_index);
}
}
ValueType const & dereference() const
{
BOOST_ASSERT(current_index <= Dispatcher::max_index(container));
return Dispatcher::get_value(Dispatcher::get_internal_value(container, current_index));
}
void discover_nodes(size_t index)
{
if (Dispatcher::is_leaf(container, index))
return;
std::pair<size_t, size_t> child_range = Dispatcher::get_child_nodes(container, index);
for (size_t i = child_range.first; i <= child_range.second; ++i)
unvisited_nodes.push(i);
}
std::priority_queue<size_t,
std::vector<size_t, typename Alloc::template rebind<size_t>::other >,
compare_by_heap_value
> unvisited_nodes;
};
} /* namespace detail */
} /* namespace heap */
} /* namespace boost */
#endif /* BOOST_HEAP_DETAIL_ORDERED_ADAPTOR_ITERATOR_HPP */

View File

@@ -0,0 +1,544 @@
// boost heap: helper classes for stable priority queues
//
// Copyright (C) 2010 Tim Blechmann
//
// 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_HEAP_DETAIL_STABLE_HEAP_HPP
#define BOOST_HEAP_DETAIL_STABLE_HEAP_HPP
#include <limits>
#include <stdexcept>
#include <utility>
#include <boost/cstdint.hpp>
#include <boost/throw_exception.hpp>
#include <boost/iterator/iterator_adaptor.hpp>
#include <boost/heap/policies.hpp>
#include <boost/heap/heap_merge.hpp>
namespace boost {
namespace heap {
namespace detail {
template<bool ConstantSize, class SizeType>
struct size_holder
{
static const bool constant_time_size = ConstantSize;
typedef SizeType size_type;
size_holder(void):
size_(0)
{}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
size_holder(size_holder && rhs):
size_(rhs.size_)
{
rhs.size_ = 0;
}
size_holder(size_holder const & rhs):
size_(rhs.size_)
{}
size_holder & operator=(size_holder && rhs)
{
size_ = rhs.size_;
rhs.size_ = 0;
return *this;
}
size_holder & operator=(size_holder const & rhs)
{
size_ = rhs.size_;
return *this;
}
#endif
SizeType get_size() const
{ return size_; }
void set_size(SizeType size)
{ size_ = size; }
void decrement()
{ --size_; }
void increment()
{ ++size_; }
void add(SizeType value)
{ size_ += value; }
void sub(SizeType value)
{ size_ -= value; }
void swap(size_holder & rhs)
{ std::swap(size_, rhs.size_); }
SizeType size_;
};
template<class SizeType>
struct size_holder<false, SizeType>
{
static const bool constant_time_size = false;
typedef SizeType size_type;
size_holder(void)
{}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
size_holder(size_holder && rhs)
{}
size_holder(size_holder const & rhs)
{}
size_holder & operator=(size_holder && rhs)
{
return *this;
}
size_holder & operator=(size_holder const & rhs)
{
return *this;
}
#endif
size_type get_size() const
{ return 0; }
void set_size(size_type)
{}
void decrement()
{}
void increment()
{}
void add(SizeType value)
{}
void sub(SizeType value)
{}
void swap(size_holder & rhs)
{}
};
// note: MSVC does not implement lookup correctly, we therefore have to place the Cmp object as member inside the
// struct. of course, this prevents EBO and significantly reduces the readability of this code
template <typename T,
typename Cmp,
bool constant_time_size,
typename StabilityCounterType = boost::uintmax_t,
bool stable = false
>
struct heap_base:
#ifndef BOOST_MSVC
Cmp,
#endif
size_holder<constant_time_size, size_t>
{
typedef StabilityCounterType stability_counter_type;
typedef T value_type;
typedef T internal_type;
typedef size_holder<constant_time_size, size_t> size_holder_type;
typedef Cmp value_compare;
typedef Cmp internal_compare;
static const bool is_stable = stable;
#ifdef BOOST_MSVC
Cmp cmp_;
#endif
heap_base (Cmp const & cmp = Cmp()):
#ifndef BOOST_MSVC
Cmp(cmp)
#else
cmp_(cmp)
#endif
{}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
heap_base(heap_base && rhs):
#ifndef BOOST_MSVC
Cmp(std::move(static_cast<Cmp&>(rhs))),
#else
cmp_(std::move(rhs.cmp_)),
#endif
size_holder_type(std::move(static_cast<size_holder_type&>(rhs)))
{}
heap_base(heap_base const & rhs):
#ifndef BOOST_MSVC
Cmp(static_cast<Cmp const &>(rhs)),
#else
cmp_(rhs.value_comp()),
#endif
size_holder_type(static_cast<size_holder_type const &>(rhs))
{}
heap_base & operator=(heap_base && rhs)
{
value_comp_ref().operator=(std::move(rhs.value_comp_ref()));
size_holder_type::operator=(std::move(static_cast<size_holder_type&>(rhs)));
return *this;
}
heap_base & operator=(heap_base const & rhs)
{
value_comp_ref().operator=(rhs.value_comp());
size_holder_type::operator=(static_cast<size_holder_type const &>(rhs));
return *this;
}
#endif
bool operator()(internal_type const & lhs, internal_type const & rhs) const
{
return value_comp().operator()(lhs, rhs);
}
internal_type make_node(T const & val)
{
return val;
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
T && make_node(T && val)
{
return std::forward<T>(val);
}
#endif
static T & get_value(internal_type & val)
{
return val;
}
static T const & get_value(internal_type const & val)
{
return val;
}
Cmp const & value_comp(void) const
{
#ifndef BOOST_MSVC
return *this;
#else
return cmp_;
#endif
}
Cmp const & get_internal_cmp(void) const
{
return value_comp();
}
void swap(heap_base & rhs)
{
std::swap(value_comp_ref(), rhs.value_comp_ref());
size_holder<constant_time_size, size_t>::swap(rhs);
}
stability_counter_type get_stability_count(void) const
{
return 0;
}
void set_stability_count(stability_counter_type)
{}
template <typename Heap1, typename Heap2>
friend struct heap_merge_emulate;
private:
Cmp & value_comp_ref(void)
{
#ifndef BOOST_MSVC
return *this;
#else
return cmp_;
#endif
}
};
template <typename T,
typename Cmp,
bool constant_time_size,
typename StabilityCounterType
>
struct heap_base<T, Cmp, constant_time_size, StabilityCounterType, true>:
#ifndef BOOST_MSVC
Cmp,
#endif
size_holder<constant_time_size, size_t>
{
typedef StabilityCounterType stability_counter_type;
typedef T value_type;
typedef std::pair<T, stability_counter_type> internal_type;
typedef size_holder<constant_time_size, size_t> size_holder_type;
typedef Cmp value_compare;
#ifdef BOOST_MSVC
Cmp cmp_;
#endif
heap_base (Cmp const & cmp = Cmp()):
#ifndef BOOST_MSVC
Cmp(cmp),
#else
cmp_(cmp),
#endif
counter_(0)
{}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
heap_base(heap_base && rhs):
#ifndef BOOST_MSVC
Cmp(std::move(static_cast<Cmp&>(rhs))),
#else
cmp_(std::move(rhs.cmp_)),
#endif
size_holder_type(std::move(static_cast<size_holder_type&>(rhs))), counter_(rhs.counter_)
{
rhs.counter_ = 0;
}
heap_base(heap_base const & rhs):
#ifndef BOOST_MSVC
Cmp(static_cast<Cmp const&>(rhs)),
#else
cmp_(rhs.value_comp()),
#endif
size_holder_type(static_cast<size_holder_type const &>(rhs)), counter_(rhs.counter_)
{}
heap_base & operator=(heap_base && rhs)
{
value_comp_ref().operator=(std::move(rhs.value_comp_ref()));
size_holder_type::operator=(std::move(static_cast<size_holder_type&>(rhs)));
counter_ = rhs.counter_;
rhs.counter_ = 0;
return *this;
}
heap_base & operator=(heap_base const & rhs)
{
value_comp_ref().operator=(rhs.value_comp());
size_holder_type::operator=(static_cast<size_holder_type const &>(rhs));
counter_ = rhs.counter_;
return *this;
}
#endif
bool operator()(internal_type const & lhs, internal_type const & rhs) const
{
return get_internal_cmp()(lhs, rhs);
}
bool operator()(T const & lhs, T const & rhs) const
{
return value_comp()(lhs, rhs);
}
internal_type make_node(T const & val)
{
stability_counter_type count = ++counter_;
if (counter_ == (std::numeric_limits<stability_counter_type>::max)())
BOOST_THROW_EXCEPTION(std::runtime_error("boost::heap counter overflow"));
return std::make_pair(val, count);
}
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class... Args>
internal_type make_node(Args&&... args)
{
stability_counter_type count = ++counter_;
if (counter_ == (std::numeric_limits<stability_counter_type>::max)())
BOOST_THROW_EXCEPTION(std::runtime_error("boost::heap counter overflow"));
return std::make_pair(std::forward<T>(args)..., count);
}
#endif
static T & get_value(internal_type & val)
{
return val.first;
}
static T const & get_value(internal_type const & val)
{
return val.first;
}
Cmp const & value_comp(void) const
{
#ifndef BOOST_MSVC
return *this;
#else
return cmp_;
#endif
}
struct internal_compare:
Cmp
{
internal_compare(Cmp const & cmp = Cmp()):
Cmp(cmp)
{}
bool operator()(internal_type const & lhs, internal_type const & rhs) const
{
if (Cmp::operator()(lhs.first, rhs.first))
return true;
if (Cmp::operator()(rhs.first, lhs.first))
return false;
return lhs.second > rhs.second;
}
};
internal_compare get_internal_cmp(void) const
{
return internal_compare(value_comp());
}
void swap(heap_base & rhs)
{
#ifndef BOOST_MSVC
std::swap(static_cast<Cmp&>(*this), static_cast<Cmp&>(rhs));
#else
std::swap(cmp_, rhs.cmp_);
#endif
std::swap(counter_, rhs.counter_);
size_holder<constant_time_size, size_t>::swap(rhs);
}
stability_counter_type get_stability_count(void) const
{
return counter_;
}
void set_stability_count(stability_counter_type new_count)
{
counter_ = new_count;
}
template <typename Heap1, typename Heap2>
friend struct heap_merge_emulate;
private:
Cmp & value_comp_ref(void)
{
#ifndef BOOST_MSVC
return *this;
#else
return cmp_;
#endif
}
stability_counter_type counter_;
};
template <typename node_pointer,
typename extractor,
typename reference
>
struct node_handle
{
explicit node_handle(node_pointer n = 0):
node_(n)
{}
reference operator*() const
{
return extractor::get_value(node_->value);
}
node_pointer node_;
};
template <typename value_type,
typename internal_type,
typename extractor
>
struct value_extractor
{
value_type const & operator()(internal_type const & data) const
{
return extractor::get_value(data);
}
};
template <typename T,
typename ContainerIterator,
typename Extractor>
class stable_heap_iterator:
public boost::iterator_adaptor<stable_heap_iterator<T, ContainerIterator, Extractor>,
ContainerIterator,
T const,
boost::random_access_traversal_tag>
{
typedef boost::iterator_adaptor<stable_heap_iterator,
ContainerIterator,
T const,
boost::random_access_traversal_tag> super_t;
public:
stable_heap_iterator(void):
super_t(0)
{}
explicit stable_heap_iterator(ContainerIterator const & it):
super_t(it)
{}
private:
friend class boost::iterator_core_access;
T const & dereference() const
{
return Extractor::get_value(*super_t::base());
}
};
template <typename T, typename Parspec, bool constant_time_size>
struct make_heap_base
{
typedef typename parameter::binding<Parspec, tag::compare, std::less<T> >::type compare_argument;
typedef typename parameter::binding<Parspec, tag::allocator, std::allocator<T> >::type allocator_argument;
typedef typename parameter::binding<Parspec, tag::stability_counter_type, boost::uintmax_t >::type stability_counter_type;
static const bool is_stable = extract_stable<Parspec>::value;
typedef heap_base<T, compare_argument, constant_time_size, stability_counter_type, is_stable> type;
};
template <typename Alloc>
struct extract_allocator_types
{
typedef typename Alloc::size_type size_type;
typedef typename Alloc::difference_type difference_type;
typedef typename Alloc::reference reference;
typedef typename Alloc::const_reference const_reference;
typedef typename Alloc::pointer pointer;
typedef typename Alloc::const_pointer const_pointer;
};
} /* namespace detail */
} /* namespace heap */
} /* namespace boost */
#endif /* BOOST_HEAP_DETAIL_STABLE_HEAP_HPP */

View File

@@ -0,0 +1,393 @@
// boost heap: node tree iterator helper classes
//
// Copyright (C) 2010 Tim Blechmann
//
// 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)
// Disclaimer: Not a Boost library.
#ifndef BOOST_HEAP_DETAIL_TREE_ITERATOR_HPP
#define BOOST_HEAP_DETAIL_TREE_ITERATOR_HPP
#include <functional>
#include <vector>
#include <boost/iterator/iterator_adaptor.hpp>
#include <queue>
namespace boost {
namespace heap {
namespace detail {
template<typename type>
struct identity:
public std::unary_function<type,type>
{
type& operator()(type& x) const
{ return x; }
const type& operator()(const type& x) const
{ return x; }
};
template<typename type>
struct caster:
public std::unary_function<type,type>
{
template <typename U>
type& operator()(U& x) const
{ return static_cast<type&>(x); }
template <typename U>
const type& operator()(const U& x) const
{ return static_cast<const type&>(x); }
};
template<typename Node>
struct dereferencer
{
template <typename Iterator>
Node * operator()(Iterator const & it)
{
return static_cast<Node *>(*it);
}
};
template<typename Node>
struct pointer_to_reference
{
template <typename Iterator>
const Node * operator()(Iterator const & it)
{
return static_cast<const Node *>(&*it);
}
};
template <typename HandleType,
typename Alloc,
typename ValueCompare
>
struct unordered_tree_iterator_storage
{
unordered_tree_iterator_storage(ValueCompare const & cmp)
{}
void push(HandleType h)
{
data_.push_back(h);
}
HandleType const & top(void)
{
return data_.back();
}
void pop(void)
{
data_.pop_back();
}
bool empty(void) const
{
return data_.empty();
}
std::vector<HandleType, typename Alloc::template rebind<HandleType>::other > data_;
};
template <typename ValueType,
typename HandleType,
typename Alloc,
typename ValueCompare,
typename ValueExtractor
>
struct ordered_tree_iterator_storage:
ValueExtractor
{
struct compare_values_by_handle:
ValueExtractor,
ValueCompare
{
compare_values_by_handle(ValueCompare const & cmp):
ValueCompare(cmp)
{}
bool operator()(HandleType const & lhs, HandleType const & rhs) const
{
ValueType const & lhs_value = ValueExtractor::operator()(lhs->value);
ValueType const & rhs_value = ValueExtractor::operator()(rhs->value);
return ValueCompare::operator()(lhs_value, rhs_value);
}
};
ordered_tree_iterator_storage(ValueCompare const & cmp):
data_(compare_values_by_handle(cmp))
{}
void push(HandleType h)
{
data_.push(h);
}
void pop(void)
{
data_.pop();
}
HandleType const & top(void)
{
return data_.top();
}
bool empty(void) const
{
return data_.empty();
}
std::priority_queue<HandleType,
std::vector<HandleType, typename Alloc::template rebind<HandleType>::other>,
compare_values_by_handle> data_;
};
/* tree iterator helper class
*
* Requirements:
* Node provides child_iterator
* ValueExtractor can convert Node->value to ValueType
*
* */
template <typename Node,
typename ValueType,
typename Alloc = std::allocator<Node>,
typename ValueExtractor = identity<typename Node::value_type>,
typename PointerExtractor = dereferencer<Node>,
bool check_null_pointer = false,
bool ordered_iterator = false,
typename ValueCompare = std::less<ValueType>
>
class tree_iterator:
public boost::iterator_adaptor<tree_iterator<Node,
ValueType,
Alloc,
ValueExtractor,
PointerExtractor,
check_null_pointer,
ordered_iterator,
ValueCompare
>,
const Node *,
ValueType,
boost::forward_traversal_tag
>,
ValueExtractor,
PointerExtractor
{
typedef boost::iterator_adaptor<tree_iterator<Node,
ValueType,
Alloc,
ValueExtractor,
PointerExtractor,
check_null_pointer,
ordered_iterator,
ValueCompare
>,
const Node *,
ValueType,
boost::forward_traversal_tag
> adaptor_type;
friend class boost::iterator_core_access;
typedef typename boost::mpl::if_c< ordered_iterator,
ordered_tree_iterator_storage<ValueType, const Node*, Alloc, ValueCompare, ValueExtractor>,
unordered_tree_iterator_storage<const Node*, Alloc, ValueCompare>
>::type
unvisited_node_container;
public:
tree_iterator(void):
adaptor_type(0), unvisited_nodes(ValueCompare())
{}
tree_iterator(ValueCompare const & cmp):
adaptor_type(0), unvisited_nodes(cmp)
{}
tree_iterator(const Node * it, ValueCompare const & cmp):
adaptor_type(it), unvisited_nodes(cmp)
{
if (it)
discover_nodes(it);
}
/* fills the iterator from a list of possible top nodes */
template <typename NodePointerIterator>
tree_iterator(NodePointerIterator begin, NodePointerIterator end, const Node * top_node, ValueCompare const & cmp):
adaptor_type(0), unvisited_nodes(cmp)
{
BOOST_STATIC_ASSERT(ordered_iterator);
if (begin == end)
return;
adaptor_type::base_reference() = top_node;
discover_nodes(top_node);
for (NodePointerIterator it = begin; it != end; ++it) {
const Node * current_node = static_cast<const Node*>(&*it);
if (current_node != top_node)
unvisited_nodes.push(current_node);
}
}
bool operator!=(tree_iterator const & rhs) const
{
return adaptor_type::base() != rhs.base();
}
bool operator==(tree_iterator const & rhs) const
{
return !operator!=(rhs);
}
const Node * get_node() const
{
return adaptor_type::base_reference();
}
private:
void increment(void)
{
if (unvisited_nodes.empty())
adaptor_type::base_reference() = 0;
else {
const Node * next = unvisited_nodes.top();
unvisited_nodes.pop();
discover_nodes(next);
adaptor_type::base_reference() = next;
}
}
ValueType const & dereference() const
{
return ValueExtractor::operator()(adaptor_type::base_reference()->value);
}
void discover_nodes(const Node * n)
{
for (typename Node::const_child_iterator it = n->children.begin(); it != n->children.end(); ++it) {
const Node * n = PointerExtractor::operator()(it);
if (check_null_pointer && n == NULL)
continue;
unvisited_nodes.push(n);
}
}
unvisited_node_container unvisited_nodes;
};
template <typename Node, typename NodeList>
struct list_iterator_converter
{
typename NodeList::const_iterator operator()(const Node * node)
{
return NodeList::s_iterator_to(*node);
}
Node * operator()(typename NodeList::const_iterator it)
{
return const_cast<Node*>(static_cast<const Node*>(&*it));
}
};
template <typename Node,
typename NodeIterator,
typename ValueType,
typename ValueExtractor = identity<typename Node::value_type>,
typename IteratorCoverter = identity<NodeIterator>
>
class recursive_tree_iterator:
public boost::iterator_adaptor<recursive_tree_iterator<Node,
NodeIterator,
ValueType,
ValueExtractor,
IteratorCoverter
>,
NodeIterator,
ValueType const,
boost::bidirectional_traversal_tag>,
ValueExtractor, IteratorCoverter
{
typedef boost::iterator_adaptor<recursive_tree_iterator<Node,
NodeIterator,
ValueType,
ValueExtractor,
IteratorCoverter
>,
NodeIterator,
ValueType const,
boost::bidirectional_traversal_tag> adaptor_type;
friend class boost::iterator_core_access;
public:
recursive_tree_iterator(void):
adaptor_type(0)
{}
explicit recursive_tree_iterator(NodeIterator const & it):
adaptor_type(it)
{}
void increment(void)
{
NodeIterator next = adaptor_type::base_reference();
const Node * n = get_node(next);
if (n->children.empty()) {
const Node * parent = get_node(next)->get_parent();
++next;
while (true) {
if (parent == NULL || next != parent->children.end())
break;
next = IteratorCoverter::operator()(parent);
parent = get_node(next)->get_parent();
++next;
}
} else
next = n->children.begin();
adaptor_type::base_reference() = next;
return;
}
ValueType const & dereference() const
{
return ValueExtractor::operator()(get_node(adaptor_type::base_reference())->value);
}
static const Node * get_node(NodeIterator const & it)
{
return static_cast<const Node *>(&*it);
}
const Node * get_node() const
{
return get_node(adaptor_type::base_reference());
}
};
} /* namespace detail */
} /* namespace heap */
} /* namespace boost */
#endif /* BOOST_HEAP_DETAIL_TREE_ITERATOR_HPP */

View File

@@ -0,0 +1,769 @@
// boost heap: fibonacci heap
//
// Copyright (C) 2010 Tim Blechmann
//
// 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_HEAP_FIBONACCI_HEAP_HPP
#define BOOST_HEAP_FIBONACCI_HEAP_HPP
#include <algorithm>
#include <utility>
#include <vector>
#include <boost/array.hpp>
#include <boost/assert.hpp>
#include <boost/heap/detail/heap_comparison.hpp>
#include <boost/heap/detail/heap_node.hpp>
#include <boost/heap/detail/stable_heap.hpp>
#include <boost/heap/detail/tree_iterator.hpp>
#ifndef BOOST_DOXYGEN_INVOKED
#ifdef BOOST_HEAP_SANITYCHECKS
#define BOOST_HEAP_ASSERT BOOST_ASSERT
#else
#define BOOST_HEAP_ASSERT(expression)
#endif
#endif
namespace boost {
namespace heap {
namespace detail {
typedef parameter::parameters<boost::parameter::optional<tag::allocator>,
boost::parameter::optional<tag::compare>,
boost::parameter::optional<tag::stable>,
boost::parameter::optional<tag::constant_time_size>,
boost::parameter::optional<tag::stability_counter_type>
> fibonacci_heap_signature;
template <typename T, typename Parspec>
struct make_fibonacci_heap_base
{
static const bool constant_time_size = parameter::binding<Parspec,
tag::constant_time_size,
boost::mpl::true_
>::type::value;
typedef typename detail::make_heap_base<T, Parspec, constant_time_size>::type base_type;
typedef typename detail::make_heap_base<T, Parspec, constant_time_size>::allocator_argument allocator_argument;
typedef typename detail::make_heap_base<T, Parspec, constant_time_size>::compare_argument compare_argument;
typedef marked_heap_node<typename base_type::internal_type> node_type;
typedef typename allocator_argument::template rebind<node_type>::other allocator_type;
struct type:
base_type,
allocator_type
{
type(compare_argument const & arg):
base_type(arg)
{}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
type(type && rhs):
base_type(std::move(static_cast<base_type&>(rhs))),
allocator_type(std::move(static_cast<allocator_type&>(rhs)))
{}
type(type & rhs):
base_type(static_cast<base_type&>(rhs)),
allocator_type(static_cast<allocator_type&>(rhs))
{}
type & operator=(type && rhs)
{
base_type::operator=(std::move(static_cast<base_type&>(rhs)));
allocator_type::operator=(std::move(static_cast<allocator_type&>(rhs)));
return *this;
}
type & operator=(type const & rhs)
{
base_type::operator=(static_cast<base_type const &>(rhs));
allocator_type::operator=(static_cast<allocator_type const &>(rhs));
return *this;
}
#endif
};
};
}
/**
* \class fibonacci_heap
* \brief fibonacci heap
*
* The template parameter T is the type to be managed by the container.
* The user can specify additional options and if no options are provided default options are used.
*
* The container supports the following options:
* - \c boost::heap::stable<>, defaults to \c stable<false>
* - \c boost::heap::compare<>, defaults to \c compare<std::less<T> >
* - \c boost::heap::allocator<>, defaults to \c allocator<std::allocator<T> >
* - \c boost::heap::constant_time_size<>, defaults to \c constant_time_size<true>
* - \c boost::heap::stability_counter_type<>, defaults to \c stability_counter_type<boost::uintmax_t>
*
*/
#ifdef BOOST_DOXYGEN_INVOKED
template<class T, class ...Options>
#else
template <typename T,
class A0 = boost::parameter::void_,
class A1 = boost::parameter::void_,
class A2 = boost::parameter::void_,
class A3 = boost::parameter::void_,
class A4 = boost::parameter::void_
>
#endif
class fibonacci_heap:
private detail::make_fibonacci_heap_base<T,
typename detail::fibonacci_heap_signature::bind<A0, A1, A2, A3, A4>::type
>::type
{
typedef typename detail::fibonacci_heap_signature::bind<A0, A1, A2, A3, A4>::type bound_args;
typedef detail::make_fibonacci_heap_base<T, bound_args> base_maker;
typedef typename base_maker::type super_t;
typedef typename super_t::size_holder_type size_holder;
typedef typename super_t::internal_type internal_type;
typedef typename base_maker::allocator_argument allocator_argument;
template <typename Heap1, typename Heap2>
friend struct heap_merge_emulate;
private:
#ifndef BOOST_DOXYGEN_INVOKED
struct implementation_defined:
detail::extract_allocator_types<typename base_maker::allocator_argument>
{
typedef T value_type;
typedef typename detail::extract_allocator_types<typename base_maker::allocator_argument>::size_type size_type;
typedef typename detail::extract_allocator_types<typename base_maker::allocator_argument>::reference reference;
typedef typename base_maker::compare_argument value_compare;
typedef typename base_maker::allocator_type allocator_type;
typedef typename allocator_type::pointer node_pointer;
typedef typename allocator_type::const_pointer const_node_pointer;
typedef detail::heap_node_list node_list_type;
typedef typename node_list_type::iterator node_list_iterator;
typedef typename node_list_type::const_iterator node_list_const_iterator;
typedef typename base_maker::node_type node;
typedef detail::value_extractor<value_type, internal_type, super_t> value_extractor;
typedef typename super_t::internal_compare internal_compare;
typedef detail::node_handle<node_pointer, super_t, reference> handle_type;
typedef detail::recursive_tree_iterator<node,
node_list_const_iterator,
const value_type,
value_extractor,
detail::list_iterator_converter<node, node_list_type>
> iterator;
typedef iterator const_iterator;
typedef detail::tree_iterator<node,
const value_type,
allocator_type,
value_extractor,
detail::list_iterator_converter<node, node_list_type>,
true,
true,
value_compare
> ordered_iterator;
};
typedef typename implementation_defined::node node;
typedef typename implementation_defined::node_pointer node_pointer;
typedef typename implementation_defined::node_list_type node_list_type;
typedef typename implementation_defined::node_list_iterator node_list_iterator;
typedef typename implementation_defined::node_list_const_iterator node_list_const_iterator;
typedef typename implementation_defined::internal_compare internal_compare;
#endif
public:
typedef T value_type;
typedef typename implementation_defined::size_type size_type;
typedef typename implementation_defined::difference_type difference_type;
typedef typename implementation_defined::value_compare value_compare;
typedef typename implementation_defined::allocator_type allocator_type;
typedef typename implementation_defined::reference reference;
typedef typename implementation_defined::const_reference const_reference;
typedef typename implementation_defined::pointer pointer;
typedef typename implementation_defined::const_pointer const_pointer;
/// \copydoc boost::heap::priority_queue::iterator
typedef typename implementation_defined::iterator iterator;
typedef typename implementation_defined::const_iterator const_iterator;
typedef typename implementation_defined::ordered_iterator ordered_iterator;
typedef typename implementation_defined::handle_type handle_type;
static const bool constant_time_size = base_maker::constant_time_size;
static const bool has_ordered_iterators = true;
static const bool is_mergable = true;
static const bool is_stable = detail::extract_stable<bound_args>::value;
static const bool has_reserve = false;
/// \copydoc boost::heap::priority_queue::priority_queue(value_compare const &)
explicit fibonacci_heap(value_compare const & cmp = value_compare()):
super_t(cmp), top_element(0)
{}
/// \copydoc boost::heap::priority_queue::priority_queue(priority_queue const &)
fibonacci_heap(fibonacci_heap const & rhs):
super_t(rhs), top_element(0)
{
if (rhs.empty())
return;
clone_forest(rhs);
size_holder::set_size(rhs.size());
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
/// \copydoc boost::heap::priority_queue::priority_queue(priority_queue &&)
fibonacci_heap(fibonacci_heap && rhs):
super_t(std::move(rhs)), top_element(rhs.top_element)
{
roots.splice(roots.begin(), rhs.roots);
rhs.top_element = NULL;
}
fibonacci_heap(fibonacci_heap & rhs):
super_t(rhs), top_element(rhs.top_element)
{
roots.splice(roots.begin(), rhs.roots);
rhs.top_element = NULL;
}
/// \copydoc boost::heap::priority_queue::operator=(priority_queue &&)
fibonacci_heap & operator=(fibonacci_heap && rhs)
{
clear();
super_t::operator=(std::move(rhs));
roots.splice(roots.begin(), rhs.roots);
top_element = rhs.top_element;
rhs.top_element = NULL;
return *this;
}
#endif
/// \copydoc boost::heap::priority_queue::operator=(priority_queue const &)
fibonacci_heap & operator=(fibonacci_heap const & rhs)
{
clear();
size_holder::set_size(rhs.size());
static_cast<super_t&>(*this) = rhs;
if (rhs.empty())
top_element = NULL;
else
clone_forest(rhs);
return *this;
}
~fibonacci_heap(void)
{
clear();
}
/// \copydoc boost::heap::priority_queue::empty
bool empty(void) const
{
if (constant_time_size)
return size() == 0;
else
return roots.empty();
}
/// \copydoc boost::heap::priority_queue::size
size_type size(void) const
{
if (constant_time_size)
return size_holder::get_size();
if (empty())
return 0;
else
return detail::count_list_nodes<node, node_list_type>(roots);
}
/// \copydoc boost::heap::priority_queue::max_size
size_type max_size(void) const
{
return allocator_type::max_size();
}
/// \copydoc boost::heap::priority_queue::clear
void clear(void)
{
typedef detail::node_disposer<node, typename node_list_type::value_type, allocator_type> disposer;
roots.clear_and_dispose(disposer(*this));
size_holder::set_size(0);
top_element = NULL;
}
/// \copydoc boost::heap::priority_queue::get_allocator
allocator_type get_allocator(void) const
{
return *this;
}
/// \copydoc boost::heap::priority_queue::swap
void swap(fibonacci_heap & rhs)
{
super_t::swap(rhs);
std::swap(top_element, rhs.top_element);
roots.swap(rhs.roots);
}
/// \copydoc boost::heap::priority_queue::top
value_type const & top(void) const
{
BOOST_ASSERT(!empty());
return super_t::get_value(top_element->value);
}
/**
* \b Effects: Adds a new element to the priority queue. Returns handle to element
*
* \b Complexity: Constant.
*
* \b Note: Does not invalidate iterators.
*
* */
handle_type push(value_type const & v)
{
size_holder::increment();
node_pointer n = allocator_type::allocate(1);
new(n) node(super_t::make_node(v));
roots.push_front(*n);
if (!top_element || super_t::operator()(top_element->value, n->value))
top_element = n;
return handle_type(n);
}
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
/**
* \b Effects: Adds a new element to the priority queue. The element is directly constructed in-place. Returns handle to element.
*
* \b Complexity: Constant.
*
* \b Note: Does not invalidate iterators.
*
* */
template <class... Args>
handle_type emplace(Args&&... args)
{
size_holder::increment();
node_pointer n = allocator_type::allocate(1);
new(n) node(super_t::make_node(std::forward<Args>(args)...));
roots.push_front(*n);
if (!top_element || super_t::operator()(top_element->value, n->value))
top_element = n;
return handle_type(n);
}
#endif
/**
* \b Effects: Removes the top element from the priority queue.
*
* \b Complexity: Logarithmic (amortized). Linear (worst case).
*
* */
void pop(void)
{
BOOST_ASSERT(!empty());
node_pointer element = top_element;
roots.erase(node_list_type::s_iterator_to(*element));
finish_erase_or_pop(element);
}
/**
* \b Effects: Assigns \c v to the element handled by \c handle & updates the priority queue.
*
* \b Complexity: Logarithmic if current value < v, Constant otherwise.
*
* */
void update (handle_type handle, const_reference v)
{
if (super_t::operator()(super_t::get_value(handle.node_->value), v))
increase(handle, v);
else
decrease(handle, v);
}
/** \copydoc boost::heap::fibonacci_heap::update(handle_type, const_reference)
*
* \b Rationale: The lazy update function is a modification of the traditional update, that just invalidates
* the iterator to the object referred to by the handle.
* */
void update_lazy(handle_type handle, const_reference v)
{
handle.node_->value = super_t::make_node(v);
update_lazy(handle);
}
/**
* \b Effects: Updates the heap after the element handled by \c handle has been changed.
*
* \b Complexity: Logarithmic.
*
* \b Note: If this is not called, after a handle has been updated, the behavior of the data structure is undefined!
* */
void update (handle_type handle)
{
node_pointer n = handle.node_;
node_pointer parent = n->get_parent();
if (parent) {
n->parent = NULL;
roots.splice(roots.begin(), parent->children, node_list_type::s_iterator_to(*n));
}
add_children_to_root(n);
consolidate();
}
/** \copydoc boost::heap::fibonacci_heap::update (handle_type handle)
*
* \b Rationale: The lazy update function is a modification of the traditional update, that just invalidates
* the iterator to the object referred to by the handle.
* */
void update_lazy (handle_type handle)
{
node_pointer n = handle.node_;
node_pointer parent = n->get_parent();
if (parent) {
n->parent = NULL;
roots.splice(roots.begin(), parent->children, node_list_type::s_iterator_to(*n));
}
add_children_to_root(n);
}
/**
* \b Effects: Assigns \c v to the element handled by \c handle & updates the priority queue.
*
* \b Complexity: Constant.
*
* \b Note: The new value is expected to be greater than the current one
* */
void increase (handle_type handle, const_reference v)
{
handle.node_->value = super_t::make_node(v);
increase(handle);
}
/**
* \b Effects: Updates the heap after the element handled by \c handle has been changed.
*
* \b Complexity: Constant.
*
* \b Note: If this is not called, after a handle has been updated, the behavior of the data structure is undefined!
* */
void increase (handle_type handle)
{
node_pointer n = handle.node_;
if (n->parent) {
if (super_t::operator()(n->get_parent()->value, n->value)) {
node_pointer parent = n->get_parent();
cut(n);
cascading_cut(parent);
}
}
if (super_t::operator()(top_element->value, n->value)) {
top_element = n;
return;
}
}
/**
* \b Effects: Assigns \c v to the element handled by \c handle & updates the priority queue.
*
* \b Complexity: Logarithmic.
*
* \b Note: The new value is expected to be less than the current one
* */
void decrease (handle_type handle, const_reference v)
{
handle.node_->value = super_t::make_node(v);
decrease(handle);
}
/**
* \b Effects: Updates the heap after the element handled by \c handle has been changed.
*
* \b Complexity: Logarithmic.
*
* \b Note: The new value is expected to be less than the current one. If this is not called, after a handle has been updated, the behavior of the data structure is undefined!
* */
void decrease (handle_type handle)
{
update(handle);
}
/**
* \b Effects: Removes the element handled by \c handle from the priority_queue.
*
* \b Complexity: Logarithmic.
* */
void erase(handle_type const & handle)
{
node_pointer element = handle.node_;
node_pointer parent = element->get_parent();
if (parent)
parent->children.erase(node_list_type::s_iterator_to(*element));
else
roots.erase(node_list_type::s_iterator_to(*element));
finish_erase_or_pop(element);
}
/// \copydoc boost::heap::priority_queue::begin
iterator begin(void) const
{
return iterator(roots.begin());
}
/// \copydoc boost::heap::priority_queue::end
iterator end(void) const
{
return iterator(roots.end());
}
/**
* \b Effects: Returns an ordered iterator to the first element contained in the priority queue.
*
* \b Note: Ordered iterators traverse the priority queue in heap order.
* */
ordered_iterator ordered_begin(void) const
{
return ordered_iterator(roots.begin(), roots.end(), top_element, super_t::value_comp());
}
/**
* \b Effects: Returns an ordered iterator to the first element contained in the priority queue.
*
* \b Note: Ordered iterators traverse the priority queue in heap order.
* */
ordered_iterator ordered_end(void) const
{
return ordered_iterator(NULL, super_t::value_comp());
}
/**
* \b Effects: Merge with priority queue rhs.
*
* \b Complexity: Constant.
*
* */
void merge(fibonacci_heap & rhs)
{
size_holder::add(rhs.get_size());
if (!top_element ||
(rhs.top_element && super_t::operator()(top_element->value, rhs.top_element->value)))
top_element = rhs.top_element;
roots.splice(roots.end(), rhs.roots);
rhs.set_size(0);
super_t::set_stability_count((std::max)(super_t::get_stability_count(),
rhs.get_stability_count()));
rhs.set_stability_count(0);
}
/// \copydoc boost::heap::d_ary_heap_mutable::s_handle_from_iterator
static handle_type s_handle_from_iterator(iterator const & it)
{
node * ptr = const_cast<node *>(it.get_node());
return handle_type(ptr);
}
/// \copydoc boost::heap::priority_queue::value_comp
value_compare const & value_comp(void) const
{
return super_t::value_comp();
}
/// \copydoc boost::heap::priority_queue::operator<(HeapType const & rhs) const
template <typename HeapType>
bool operator<(HeapType const & rhs) const
{
return detail::heap_compare(*this, rhs);
}
/// \copydoc boost::heap::priority_queue::operator>(HeapType const & rhs) const
template <typename HeapType>
bool operator>(HeapType const & rhs) const
{
return detail::heap_compare(rhs, *this);
}
/// \copydoc boost::heap::priority_queue::operator>=(HeapType const & rhs) const
template <typename HeapType>
bool operator>=(HeapType const & rhs) const
{
return !operator<(rhs);
}
/// \copydoc boost::heap::priority_queue::operator<=(HeapType const & rhs) const
template <typename HeapType>
bool operator<=(HeapType const & rhs) const
{
return !operator>(rhs);
}
/// \copydoc boost::heap::priority_queue::operator==(HeapType const & rhs) const
template <typename HeapType>
bool operator==(HeapType const & rhs) const
{
return detail::heap_equality(*this, rhs);
}
/// \copydoc boost::heap::priority_queue::operator!=(HeapType const & rhs) const
template <typename HeapType>
bool operator!=(HeapType const & rhs) const
{
return !(*this == rhs);
}
private:
#if !defined(BOOST_DOXYGEN_INVOKED)
void clone_forest(fibonacci_heap const & rhs)
{
BOOST_HEAP_ASSERT(roots.empty());
typedef typename node::template node_cloner<allocator_type> node_cloner;
roots.clone_from(rhs.roots, node_cloner(*this, NULL), detail::nop_disposer());
top_element = detail::find_max_child<node_list_type, node, internal_compare>(roots, super_t::get_internal_cmp());
}
void cut(node_pointer n)
{
node_pointer parent = n->get_parent();
roots.splice(roots.begin(), parent->children, node_list_type::s_iterator_to(*n));
n->parent = 0;
n->mark = false;
}
void cascading_cut(node_pointer n)
{
node_pointer parent = n->get_parent();
if (parent) {
if (!parent->mark)
parent->mark = true;
else {
cut(n);
cascading_cut(parent);
}
}
}
void add_children_to_root(node_pointer n)
{
for (node_list_iterator it = n->children.begin(); it != n->children.end(); ++it) {
node_pointer child = static_cast<node_pointer>(&*it);
child->parent = 0;
}
roots.splice(roots.end(), n->children);
}
void consolidate(void)
{
if (roots.empty())
return;
static const size_type max_log2 = sizeof(size_type) * 8;
boost::array<node_pointer, max_log2> aux;
aux.assign(NULL);
node_list_iterator it = roots.begin();
top_element = static_cast<node_pointer>(&*it);
do {
node_pointer n = static_cast<node_pointer>(&*it);
++it;
size_type node_rank = n->child_count();
if (aux[node_rank] == NULL)
aux[node_rank] = n;
else {
do {
node_pointer other = aux[node_rank];
if (super_t::operator()(n->value, other->value))
std::swap(n, other);
if (other->parent)
n->children.splice(n->children.end(), other->parent->children, node_list_type::s_iterator_to(*other));
else
n->children.splice(n->children.end(), roots, node_list_type::s_iterator_to(*other));
other->parent = n;
aux[node_rank] = NULL;
node_rank = n->child_count();
} while (aux[node_rank] != NULL);
aux[node_rank] = n;
}
if (super_t::operator()(top_element->value, n->value))
top_element = n;
}
while (it != roots.end());
}
void finish_erase_or_pop(node_pointer erased_node)
{
add_children_to_root(erased_node);
erased_node->~node();
allocator_type::deallocate(erased_node, 1);
size_holder::decrement();
if (!empty())
consolidate();
else
top_element = NULL;
}
mutable node_pointer top_element;
node_list_type roots;
#endif
};
} /* namespace heap */
} /* namespace boost */
#undef BOOST_HEAP_ASSERT
#endif /* BOOST_HEAP_FIBONACCI_HEAP_HPP */

View File

@@ -0,0 +1,103 @@
// boost heap: concepts
//
// Copyright (C) 2010 Tim Blechmann
//
// 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_HEAP_CONCEPTS_HPP
#define BOOST_HEAP_CONCEPTS_HPP
#include <boost/concept_check.hpp>
namespace boost {
namespace heap {
template <class C>
struct PriorityQueue:
boost::ForwardContainer<C>
{
typedef typename C::iterator iterator;
typedef typename C::const_iterator const_iterator;
typedef typename C::allocator_type allocator_type;
typedef typename C::value_compare value_compare;
typedef typename C::value_type value_type;
typedef typename C::const_reference const_reference;
BOOST_CONCEPT_USAGE(PriorityQueue)
{
BOOST_CONCEPT_ASSERT((boost::Assignable<value_type>));
BOOST_CONCEPT_ASSERT((boost::Container<C>));
BOOST_CONCEPT_ASSERT((boost::EqualityComparable<C>));
BOOST_CONCEPT_ASSERT((boost::Comparable<C>));
BOOST_CONCEPT_ASSERT((boost::Const_BinaryPredicate<value_compare, value_type, value_type>));
c.swap(c2);
c.clear();
a = c.get_allocator();
typename PriorityQueue::value_type v;
c.push(v);
v = c.top();
c.pop();
cmp = c.value_comp();
// verify tags
has_ordered_iterators = C::has_ordered_iterators;
is_mergable = C::is_mergable;
is_stable = C::is_stable;
}
private:
C c, c2;
allocator_type a;
typename C::value_type v;
value_compare cmp;
bool has_ordered_iterators, is_mergable, is_stable;
};
template <class C>
struct MergablePriorityQueue:
PriorityQueue<C>
{
BOOST_CONCEPT_USAGE(MergablePriorityQueue)
{
C c, c2;
c.merge(c2);
}
};
template <class C>
struct MutablePriorityQueue:
PriorityQueue<C>
{
typedef typename C::handle_type handle_type;
BOOST_CONCEPT_USAGE(MutablePriorityQueue)
{
BOOST_CONCEPT_ASSERT((boost::Assignable<typename MutablePriorityQueue::handle_type>));
typename MutablePriorityQueue::value_type v;
typename MutablePriorityQueue::handle_type h = c.push(v);
c.update(h, v);
c.increase(h, v);
c.decrease(h, v);
c.update(h);
c.increase(h);
c.decrease(h);
}
C c;
};
}}
#endif /* BOOST_HEAP_CONCEPTS_HPP */

View File

@@ -0,0 +1,125 @@
// boost heap: heap merge algorithms
//
// Copyright (C) 2011 Tim Blechmann
//
// 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_HEAP_MERGE_HPP
#define BOOST_HEAP_MERGE_HPP
#include <boost/concept/assert.hpp>
#include <boost/heap/heap_concepts.hpp>
#include <boost/type_traits/is_same.hpp>
namespace boost {
namespace heap {
namespace detail {
template <typename Heap1, typename Heap2>
struct heap_merge_emulate
{
struct dummy_reserver
{
static void reserve (Heap1 & lhs, std::size_t required_size)
{}
};
struct reserver
{
static void reserve (Heap1 & lhs, std::size_t required_size)
{
lhs.reserve(required_size);
}
};
typedef typename boost::mpl::if_c<Heap1::has_reserve,
reserver,
dummy_reserver>::type space_reserver;
static void merge(Heap1 & lhs, Heap2 & rhs)
{
if (Heap1::constant_time_size && Heap2::constant_time_size) {
if (Heap1::has_reserve) {
std::size_t required_size = lhs.size() + rhs.size();
space_reserver::reserve(lhs, required_size);
}
}
// FIXME: container adaptors could benefit from first appending all elements and then restoring the heap order
// FIXME: optimize: if we have ordered iterators and we can efficiently insert keys with a below the lowest key in the heap
// d-ary, b and fibonacci heaps fall into this category
while (!rhs.empty()) {
lhs.push(rhs.top());
rhs.pop();
}
lhs.set_stability_count((std::max)(lhs.get_stability_count(),
rhs.get_stability_count()));
rhs.set_stability_count(0);
}
};
template <typename Heap>
struct heap_merge_same_mergable
{
static void merge(Heap & lhs, Heap & rhs)
{
lhs.merge(rhs);
}
};
template <typename Heap>
struct heap_merge_same
{
static const bool is_mergable = Heap::is_mergable;
typedef typename boost::mpl::if_c<is_mergable,
heap_merge_same_mergable<Heap>,
heap_merge_emulate<Heap, Heap>
>::type heap_merger;
static void merge(Heap & lhs, Heap & rhs)
{
heap_merger::merge(lhs, rhs);
}
};
} /* namespace detail */
/** merge rhs into lhs
*
* \b Effect: lhs contains all elements that have been part of rhs, rhs is empty.
*
* */
template <typename Heap1,
typename Heap2
>
void heap_merge(Heap1 & lhs, Heap2 & rhs)
{
BOOST_CONCEPT_ASSERT((boost::heap::PriorityQueue<Heap1>));
BOOST_CONCEPT_ASSERT((boost::heap::PriorityQueue<Heap2>));
// if this assertion is triggered, the value_compare types are incompatible
BOOST_STATIC_ASSERT((boost::is_same<typename Heap1::value_compare, typename Heap2::value_compare>::value));
const bool same_heaps = boost::is_same<Heap1, Heap2>::value;
typedef typename boost::mpl::if_c<same_heaps,
detail::heap_merge_same<Heap1>,
detail::heap_merge_emulate<Heap1, Heap2>
>::type heap_merger;
heap_merger::merge(lhs, rhs);
}
} /* namespace heap */
} /* namespace boost */
#endif /* BOOST_HEAP_MERGE_HPP */

View File

@@ -0,0 +1,708 @@
// boost heap: pairing heap
//
// Copyright (C) 2010 Tim Blechmann
//
// 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_HEAP_PAIRING_HEAP_HPP
#define BOOST_HEAP_PAIRING_HEAP_HPP
#include <algorithm>
#include <utility>
#include <vector>
#include <boost/assert.hpp>
#include <boost/heap/detail/heap_comparison.hpp>
#include <boost/heap/detail/heap_node.hpp>
#include <boost/heap/policies.hpp>
#include <boost/heap/detail/stable_heap.hpp>
#include <boost/heap/detail/tree_iterator.hpp>
#ifndef BOOST_DOXYGEN_INVOKED
#ifdef BOOST_HEAP_SANITYCHECKS
#define BOOST_HEAP_ASSERT BOOST_ASSERT
#else
#define BOOST_HEAP_ASSERT(expression)
#endif
#endif
namespace boost {
namespace heap {
namespace detail {
typedef parameter::parameters<boost::parameter::optional<tag::allocator>,
boost::parameter::optional<tag::compare>,
boost::parameter::optional<tag::stable>,
boost::parameter::optional<tag::constant_time_size>,
boost::parameter::optional<tag::stability_counter_type>
> pairing_heap_signature;
template <typename T, typename Parspec>
struct make_pairing_heap_base
{
static const bool constant_time_size = parameter::binding<Parspec,
tag::constant_time_size,
boost::mpl::true_
>::type::value;
typedef typename detail::make_heap_base<T, Parspec, constant_time_size>::type base_type;
typedef typename detail::make_heap_base<T, Parspec, constant_time_size>::allocator_argument allocator_argument;
typedef typename detail::make_heap_base<T, Parspec, constant_time_size>::compare_argument compare_argument;
typedef heap_node<typename base_type::internal_type, false> node_type;
typedef typename allocator_argument::template rebind<node_type>::other allocator_type;
struct type:
base_type,
allocator_type
{
type(compare_argument const & arg):
base_type(arg)
{}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
type(type const & rhs):
base_type(rhs), allocator_type(rhs)
{}
type(type && rhs):
base_type(std::move(static_cast<base_type&>(rhs))),
allocator_type(std::move(static_cast<allocator_type&>(rhs)))
{}
type & operator=(type && rhs)
{
base_type::operator=(std::move(static_cast<base_type&>(rhs)));
allocator_type::operator=(std::move(static_cast<allocator_type&>(rhs)));
return *this;
}
type & operator=(type const & rhs)
{
base_type::operator=(static_cast<base_type const &>(rhs));
allocator_type::operator=(static_cast<const allocator_type&>(rhs));
return *this;
}
#endif
};
};
}
/**
* \class pairing_heap
* \brief pairing heap
*
* Pairing heaps are self-adjusting binary 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
*
* The template parameter T is the type to be managed by the container.
* The user can specify additional options and if no options are provided default options are used.
*
* The container supports the following options:
* - \c boost::heap::compare<>, defaults to \c compare<std::less<T> >
* - \c boost::heap::stable<>, defaults to \c stable<false>
* - \c boost::heap::stability_counter_type<>, defaults to \c stability_counter_type<boost::uintmax_t>
* - \c boost::heap::allocator<>, defaults to \c allocator<std::allocator<T> >
* - \c boost::heap::constant_time_size<>, defaults to \c constant_time_size<true>
*
*
*/
#ifdef BOOST_DOXYGEN_INVOKED
template<class T, class ...Options>
#else
template <typename T,
class A0 = boost::parameter::void_,
class A1 = boost::parameter::void_,
class A2 = boost::parameter::void_,
class A3 = boost::parameter::void_,
class A4 = boost::parameter::void_
>
#endif
class pairing_heap:
private detail::make_pairing_heap_base<T,
typename detail::pairing_heap_signature::bind<A0, A1, A2, A3, A4>::type
>::type
{
typedef typename detail::pairing_heap_signature::bind<A0, A1, A2, A3, A4>::type bound_args;
typedef detail::make_pairing_heap_base<T, bound_args> base_maker;
typedef typename base_maker::type super_t;
typedef typename super_t::internal_type internal_type;
typedef typename super_t::size_holder_type size_holder;
typedef typename base_maker::allocator_argument allocator_argument;
private:
template <typename Heap1, typename Heap2>
friend struct heap_merge_emulate;
#ifndef BOOST_DOXYGEN_INVOKED
struct implementation_defined:
detail::extract_allocator_types<typename base_maker::allocator_argument>
{
typedef T value_type;
typedef typename detail::extract_allocator_types<typename base_maker::allocator_argument>::size_type size_type;
typedef typename detail::extract_allocator_types<typename base_maker::allocator_argument>::reference reference;
typedef typename base_maker::compare_argument value_compare;
typedef typename base_maker::allocator_type allocator_type;
typedef typename allocator_type::pointer node_pointer;
typedef typename allocator_type::const_pointer const_node_pointer;
typedef detail::heap_node_list node_list_type;
typedef typename node_list_type::iterator node_list_iterator;
typedef typename node_list_type::const_iterator node_list_const_iterator;
typedef typename base_maker::node_type node;
typedef detail::value_extractor<value_type, internal_type, super_t> value_extractor;
typedef typename super_t::internal_compare internal_compare;
typedef detail::node_handle<node_pointer, super_t, reference> handle_type;
typedef detail::tree_iterator<node,
const value_type,
allocator_type,
value_extractor,
detail::pointer_to_reference<node>,
false,
false,
value_compare
> iterator;
typedef iterator const_iterator;
typedef detail::tree_iterator<node,
const value_type,
allocator_type,
value_extractor,
detail::pointer_to_reference<node>,
false,
true,
value_compare
> ordered_iterator;
};
typedef typename implementation_defined::node node;
typedef typename implementation_defined::node_pointer node_pointer;
typedef typename implementation_defined::node_list_type node_list_type;
typedef typename implementation_defined::node_list_iterator node_list_iterator;
typedef typename implementation_defined::node_list_const_iterator node_list_const_iterator;
typedef typename implementation_defined::internal_compare internal_compare;
typedef boost::intrusive::list<detail::heap_node_base<true>,
boost::intrusive::constant_time_size<false>
> node_child_list;
#endif
public:
typedef T value_type;
typedef typename implementation_defined::size_type size_type;
typedef typename implementation_defined::difference_type difference_type;
typedef typename implementation_defined::value_compare value_compare;
typedef typename implementation_defined::allocator_type allocator_type;
typedef typename implementation_defined::reference reference;
typedef typename implementation_defined::const_reference const_reference;
typedef typename implementation_defined::pointer pointer;
typedef typename implementation_defined::const_pointer const_pointer;
/// \copydoc boost::heap::priority_queue::iterator
typedef typename implementation_defined::iterator iterator;
typedef typename implementation_defined::const_iterator const_iterator;
typedef typename implementation_defined::ordered_iterator ordered_iterator;
typedef typename implementation_defined::handle_type handle_type;
static const bool constant_time_size = super_t::constant_time_size;
static const bool has_ordered_iterators = true;
static const bool is_mergable = true;
static const bool is_stable = detail::extract_stable<bound_args>::value;
static const bool has_reserve = false;
/// \copydoc boost::heap::priority_queue::priority_queue(value_compare const &)
explicit pairing_heap(value_compare const & cmp = value_compare()):
super_t(cmp), root(NULL)
{}
/// \copydoc boost::heap::priority_queue::priority_queue(priority_queue const &)
pairing_heap(pairing_heap const & rhs):
super_t(rhs), root(NULL)
{
if (rhs.empty())
return;
clone_tree(rhs);
size_holder::set_size(rhs.get_size());
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
/// \copydoc boost::heap::priority_queue::priority_queue(priority_queue &&)
pairing_heap(pairing_heap && rhs):
super_t(std::move(rhs)), root(rhs.root)
{
rhs.root = NULL;
}
/// \copydoc boost::heap::priority_queue::operator=(priority_queue &&)
pairing_heap & operator=(pairing_heap && rhs)
{
super_t::operator=(std::move(rhs));
root = rhs.root;
rhs.root = NULL;
return *this;
}
#endif
/// \copydoc boost::heap::priority_queue::operator=(priority_queue const & rhs)
pairing_heap & operator=(pairing_heap const & rhs)
{
clear();
size_holder::set_size(rhs.get_size());
static_cast<super_t&>(*this) = rhs;
clone_tree(rhs);
return *this;
}
~pairing_heap(void)
{
while (!empty())
pop();
}
/// \copydoc boost::heap::priority_queue::empty
bool empty(void) const
{
return root == NULL;
}
/// \copydoc boost::heap::binomial_heap::size
size_type size(void) const
{
if (constant_time_size)
return size_holder::get_size();
if (root == NULL)
return 0;
else
return detail::count_nodes(root);
}
/// \copydoc boost::heap::priority_queue::max_size
size_type max_size(void) const
{
return allocator_type::max_size();
}
/// \copydoc boost::heap::priority_queue::clear
void clear(void)
{
if (empty())
return;
root->template clear_subtree<allocator_type>(*this);
root->~node();
allocator_type::deallocate(root, 1);
root = NULL;
size_holder::set_size(0);
}
/// \copydoc boost::heap::priority_queue::get_allocator
allocator_type get_allocator(void) const
{
return *this;
}
/// \copydoc boost::heap::priority_queue::swap
void swap(pairing_heap & rhs)
{
super_t::swap(rhs);
std::swap(root, rhs.root);
}
/// \copydoc boost::heap::priority_queue::top
const_reference top(void) const
{
BOOST_ASSERT(!empty());
return super_t::get_value(root->value);
}
/**
* \b Effects: Adds a new element to the priority queue. Returns handle to element
*
* \cond
* \b Complexity: \f$2^2log(log(N))\f$ (amortized).
* \endcond
*
* \b Complexity: 2**2*log(log(N)) (amortized).
*
* */
handle_type push(value_type const & v)
{
size_holder::increment();
node_pointer n = allocator_type::allocate(1);
new(n) node(super_t::make_node(v));
merge_node(n);
return handle_type(n);
}
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
/**
* \b Effects: Adds a new element to the priority queue. The element is directly constructed in-place. Returns handle to element.
*
* \cond
* \b Complexity: \f$2^2log(log(N))\f$ (amortized).
* \endcond
*
* \b Complexity: 2**2*log(log(N)) (amortized).
*
* */
template <class... Args>
handle_type emplace(Args&&... args)
{
size_holder::increment();
node_pointer n = allocator_type::allocate(1);
new(n) node(super_t::make_node(std::forward<T>(args)...));
merge_node(n);
return handle_type(n);
}
#endif
/**
* \b Effects: Removes the top element from the priority queue.
*
* \b Complexity: Logarithmic (amortized).
*
* */
void pop(void)
{
BOOST_ASSERT(!empty());
erase(handle_type(root));
}
/**
* \b Effects: Assigns \c v to the element handled by \c handle & updates the priority queue.
*
* \cond
* \b Complexity: \f$2^2log(log(N))\f$ (amortized).
* \endcond
*
* \b Complexity: 2**2*log(log(N)) (amortized).
*
* */
void update (handle_type handle, const_reference v)
{
handle.node_->value = super_t::make_node(v);
update(handle);
}
/**
* \b Effects: Updates the heap after the element handled by \c handle has been changed.
*
* \cond
* \b Complexity: \f$2^2log(log(N))\f$ (amortized).
* \endcond
*
* \b Complexity: 2**2*log(log(N)) (amortized).
*
* \b Note: If this is not called, after a handle has been updated, the behavior of the data structure is undefined!
* */
void update (handle_type handle)
{
node_pointer n = handle.node_;
n->unlink();
if (!n->children.empty())
n = merge_nodes(n, merge_node_list(n->children));
if (n != root)
merge_node(n);
}
/**
* \b Effects: Assigns \c v to the element handled by \c handle & updates the priority queue.
*
* \cond
* \b Complexity: \f$2^2log(log(N))\f$ (amortized).
* \endcond
*
* \b Complexity: 2**2*log(log(N)) (amortized).
*
* \b Note: The new value is expected to be greater than the current one
* */
void increase (handle_type handle, const_reference v)
{
update(handle, v);
}
/**
* \b Effects: Updates the heap after the element handled by \c handle has been changed.
*
* \cond
* \b Complexity: \f$2^2log(log(N))\f$ (amortized).
* \endcond
*
* \b Complexity: 2**2*log(log(N)) (amortized).
*
* \b Note: If this is not called, after a handle has been updated, the behavior of the data structure is undefined!
* */
void increase (handle_type handle)
{
update(handle);
}
/**
* \b Effects: Assigns \c v to the element handled by \c handle & updates the priority queue.
*
* \cond
* \b Complexity: \f$2^2log(log(N))\f$ (amortized).
* \endcond
*
* \b Complexity: 2**2*log(log(N)) (amortized).
*
* \b Note: The new value is expected to be less than the current one
* */
void decrease (handle_type handle, const_reference v)
{
update(handle, v);
}
/**
* \b Effects: Updates the heap after the element handled by \c handle has been changed.
*
* \cond
* \b Complexity: \f$2^2log(log(N))\f$ (amortized).
* \endcond
*
* \b Complexity: 2**2*log(log(N)) (amortized).
*
* \b Note: The new value is expected to be less than the current one. If this is not called, after a handle has been updated, the behavior of the data structure is undefined!
* */
void decrease (handle_type handle)
{
update(handle);
}
/**
* \b Effects: Removes the element handled by \c handle from the priority_queue.
*
* \cond
* \b Complexity: \f$2^2log(log(N))\f$ (amortized).
* \endcond
*
* \b Complexity: 2**2*log(log(N)) (amortized).
* */
void erase(handle_type handle)
{
node_pointer n = handle.node_;
if (n != root) {
n->unlink();
if (!n->children.empty())
merge_node(merge_node_list(n->children));
} else {
if (!n->children.empty())
root = merge_node_list(n->children);
else
root = NULL;
}
size_holder::decrement();
n->~node();
allocator_type::deallocate(n, 1);
}
/// \copydoc boost::heap::priority_queue::begin
iterator begin(void) const
{
return iterator(root, super_t::value_comp());
}
/// \copydoc boost::heap::priority_queue::end
iterator end(void) const
{
return iterator();
}
/// \copydoc boost::heap::fibonacci_heap::ordered_begin
ordered_iterator ordered_begin(void) const
{
return ordered_iterator(root, super_t::value_comp());
}
/// \copydoc boost::heap::fibonacci_heap::ordered_begin
ordered_iterator ordered_end(void) const
{
return ordered_iterator(NULL, super_t::value_comp());
}
/// \copydoc boost::heap::d_ary_heap_mutable::s_handle_from_iterator
static handle_type s_handle_from_iterator(iterator const & it)
{
node * ptr = const_cast<node *>(it.get_node());
return handle_type(ptr);
}
/**
* \b Effects: Merge all elements from rhs into this
*
* \cond
* \b Complexity: \f$2^2log(log(N))\f$ (amortized).
* \endcond
*
* \b Complexity: 2**2*log(log(N)) (amortized).
*
* */
void merge(pairing_heap & rhs)
{
if (rhs.empty())
return;
merge_node(rhs.root);
size_holder::add(rhs.get_size());
rhs.set_size(0);
rhs.root = NULL;
super_t::set_stability_count((std::max)(super_t::get_stability_count(),
rhs.get_stability_count()));
rhs.set_stability_count(0);
}
/// \copydoc boost::heap::priority_queue::value_comp
value_compare const & value_comp(void) const
{
return super_t::value_comp();
}
/// \copydoc boost::heap::priority_queue::operator<(HeapType const & rhs) const
template <typename HeapType>
bool operator<(HeapType const & rhs) const
{
return detail::heap_compare(*this, rhs);
}
/// \copydoc boost::heap::priority_queue::operator>(HeapType const & rhs) const
template <typename HeapType>
bool operator>(HeapType const & rhs) const
{
return detail::heap_compare(rhs, *this);
}
/// \copydoc boost::heap::priority_queue::operator>=(HeapType const & rhs) const
template <typename HeapType>
bool operator>=(HeapType const & rhs) const
{
return !operator<(rhs);
}
/// \copydoc boost::heap::priority_queue::operator<=(HeapType const & rhs) const
template <typename HeapType>
bool operator<=(HeapType const & rhs) const
{
return !operator>(rhs);
}
/// \copydoc boost::heap::priority_queue::operator==(HeapType const & rhs) const
template <typename HeapType>
bool operator==(HeapType const & rhs) const
{
return detail::heap_equality(*this, rhs);
}
/// \copydoc boost::heap::priority_queue::operator!=(HeapType const & rhs) const
template <typename HeapType>
bool operator!=(HeapType const & rhs) const
{
return !(*this == rhs);
}
private:
#if !defined(BOOST_DOXYGEN_INVOKED)
void clone_tree(pairing_heap const & rhs)
{
BOOST_HEAP_ASSERT(root == NULL);
if (rhs.empty())
return;
root = allocator_type::allocate(1);
new(root) node(static_cast<node const &>(*rhs.root), static_cast<allocator_type&>(*this));
}
void merge_node(node_pointer other)
{
BOOST_HEAP_ASSERT(other);
if (root != NULL)
root = merge_nodes(root, other);
else
root = other;
}
node_pointer merge_node_list(node_child_list & children)
{
BOOST_HEAP_ASSERT(!children.empty());
node_pointer merged = merge_first_pair(children);
if (children.empty())
return merged;
node_child_list node_list;
node_list.push_back(*merged);
do {
node_pointer next_merged = merge_first_pair(children);
node_list.push_back(*next_merged);
} while (!children.empty());
return merge_node_list(node_list);
}
node_pointer merge_first_pair(node_child_list & children)
{
BOOST_HEAP_ASSERT(!children.empty());
node_pointer first_child = static_cast<node_pointer>(&children.front());
children.pop_front();
if (children.empty())
return first_child;
node_pointer second_child = static_cast<node_pointer>(&children.front());
children.pop_front();
return merge_nodes(first_child, second_child);
}
node_pointer merge_nodes(node_pointer node1, node_pointer node2)
{
if (super_t::operator()(node1->value, node2->value))
std::swap(node1, node2);
node2->unlink();
node1->children.push_front(*node2);
return node1;
}
node_pointer root;
#endif
};
} /* namespace heap */
} /* namespace boost */
#undef BOOST_HEAP_ASSERT
#endif /* BOOST_HEAP_PAIRING_HEAP_HPP */

View File

@@ -0,0 +1,169 @@
// boost heap
//
// Copyright (C) 2010-2011 Tim Blechmann
//
// 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_HEAP_POLICIES_HPP
#define BOOST_HEAP_POLICIES_HPP
#include <boost/parameter.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/void.hpp>
#include <boost/concept_check.hpp>
namespace boost {
namespace heap {
#ifndef BOOST_DOXYGEN_INVOKED
BOOST_PARAMETER_TEMPLATE_KEYWORD(allocator)
BOOST_PARAMETER_TEMPLATE_KEYWORD(compare)
namespace tag { struct stable; }
template <bool T>
struct stable:
boost::parameter::template_keyword<tag::stable, boost::mpl::bool_<T> >
{};
namespace tag { struct mutable_; }
template <bool T>
struct mutable_:
boost::parameter::template_keyword<tag::mutable_, boost::mpl::bool_<T> >
{};
namespace tag { struct constant_time_size; }
template <bool T>
struct constant_time_size:
boost::parameter::template_keyword<tag::constant_time_size, boost::mpl::bool_<T> >
{};
namespace tag { struct store_parent_pointer; }
template <bool T>
struct store_parent_pointer:
boost::parameter::template_keyword<tag::store_parent_pointer, boost::mpl::bool_<T> >
{};
namespace tag { struct arity; }
template <unsigned int T>
struct arity:
boost::parameter::template_keyword<tag::arity, boost::mpl::int_<T> >
{};
namespace tag { struct objects_per_page; }
template <unsigned int T>
struct objects_per_page:
boost::parameter::template_keyword<tag::objects_per_page, boost::mpl::int_<T> >
{};
BOOST_PARAMETER_TEMPLATE_KEYWORD(stability_counter_type)
namespace detail {
namespace mpl = boost::mpl;
template <typename bound_args, typename tag_type>
struct has_arg
{
typedef typename boost::parameter::binding<bound_args, tag_type, mpl::void_>::type type;
static const bool value = mpl::is_not_void_<type>::type::value;
};
template <typename bound_args>
struct extract_stable
{
static const bool has_stable = has_arg<bound_args, tag::stable>::value;
typedef typename mpl::if_c<has_stable,
typename has_arg<bound_args, tag::stable>::type,
mpl::bool_<false>
>::type stable_t;
static const bool value = stable_t::value;
};
template <typename bound_args>
struct extract_mutable
{
static const bool has_mutable = has_arg<bound_args, tag::mutable_>::value;
typedef typename mpl::if_c<has_mutable,
typename has_arg<bound_args, tag::mutable_>::type,
mpl::bool_<false>
>::type mutable_t;
static const bool value = mutable_t::value;
};
}
#else
/** \brief Specifies the predicate for the heap order
*/
template <typename T>
struct compare{};
/** \brief Configure heap as mutable
*
* Certain heaps need to be configured specifically do be mutable.
*
* */
template <bool T>
struct mutable_{};
/** \brief Specifies allocator for the internal memory management
*/
template <typename T>
struct allocator{};
/** \brief Configure a heap as \b stable
*
* A priority queue is stable, if elements with the same priority are popped from the heap, in the same order as
* they are inserted.
* */
template <bool T>
struct stable{};
/** \brief Specifies the type for stability counter
*
* */
template <typename IntType>
struct stability_counter_type{};
/** \brief Configures complexity of <tt> size() </tt>
*
* Specifies, whether size() should have linear or constant complexity.
* */
template <bool T>
struct constant_time_size{};
/** \brief Store parent pointer in heap node.
*
* Maintaining a parent pointer adds some maintenance and size overhead, but iterating a heap is more efficient.
* */
template <bool T>
struct store_parent_pointer{};
/** \brief Specify arity.
*
* Specifies the arity of a D-ary heap
* */
template <unsigned int T>
struct arity{};
#endif
} /* namespace heap */
} /* namespace boost */
#endif /* BOOST_HEAP_POLICIES_HPP */

View File

@@ -0,0 +1,405 @@
// boost heap: wrapper for stl heap
//
// Copyright (C) 2010 Tim Blechmann
//
// 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_HEAP_PRIORITY_QUEUE_HPP
#define BOOST_HEAP_PRIORITY_QUEUE_HPP
#include <algorithm>
#include <queue>
#include <utility>
#include <vector>
#include <boost/assert.hpp>
#include <boost/heap/detail/heap_comparison.hpp>
#include <boost/heap/detail/stable_heap.hpp>
namespace boost {
namespace heap {
namespace detail {
typedef parameter::parameters<boost::parameter::optional<tag::allocator>,
boost::parameter::optional<tag::compare>,
boost::parameter::optional<tag::stable>,
boost::parameter::optional<tag::stability_counter_type>
> priority_queue_signature;
}
/**
* \class priority_queue
* \brief priority queue, based on stl heap functions
*
* The priority_queue class is a wrapper for the stl heap functions.<br>
* The template parameter T is the type to be managed by the container.
* The user can specify additional options and if no options are provided default options are used.
*
* The container supports the following options:
* - \c boost::heap::compare<>, defaults to \c compare<std::less<T> >
* - \c boost::heap::stable<>, defaults to \c stable<false>
* - \c boost::heap::stability_counter_type<>, defaults to \c stability_counter_type<boost::uintmax_t>
* - \c boost::heap::allocator<>, defaults to \c allocator<std::allocator<T> >
*
*/
#ifdef BOOST_DOXYGEN_INVOKED
template<class T, class ...Options>
#else
template <typename T,
class A0 = boost::parameter::void_,
class A1 = boost::parameter::void_,
class A2 = boost::parameter::void_,
class A3 = boost::parameter::void_
>
#endif
class priority_queue:
private detail::make_heap_base<T, typename detail::priority_queue_signature::bind<A0, A1, A2, A3>::type, false>::type
{
typedef detail::make_heap_base<T, typename detail::priority_queue_signature::bind<A0, A1, A2, A3>::type, false> heap_base_maker;
typedef typename heap_base_maker::type super_t;
typedef typename super_t::internal_type internal_type;
typedef typename heap_base_maker::allocator_argument::template rebind<internal_type>::other internal_type_allocator;
typedef std::vector<internal_type, internal_type_allocator> container_type;
template <typename Heap1, typename Heap2>
friend struct detail::heap_merge_emulate;
container_type q_;
#ifndef BOOST_DOXYGEN_INVOKED
struct implementation_defined:
detail::extract_allocator_types<typename heap_base_maker::allocator_argument>
{
typedef typename heap_base_maker::compare_argument value_compare;
typedef detail::stable_heap_iterator<T, typename container_type::const_iterator, super_t> iterator;
typedef iterator const_iterator;
typedef typename container_type::allocator_type allocator_type;
};
#endif
public:
typedef T value_type;
typedef typename implementation_defined::size_type size_type;
typedef typename implementation_defined::difference_type difference_type;
typedef typename implementation_defined::value_compare value_compare;
typedef typename implementation_defined::allocator_type allocator_type;
typedef typename implementation_defined::reference reference;
typedef typename implementation_defined::const_reference const_reference;
typedef typename implementation_defined::pointer pointer;
typedef typename implementation_defined::const_pointer const_pointer;
/**
* \b Note: The iterator does not traverse the priority queue in order of the priorities.
* */
typedef typename implementation_defined::iterator iterator;
typedef typename implementation_defined::const_iterator const_iterator;
static const bool constant_time_size = true;
static const bool has_ordered_iterators = false;
static const bool is_mergable = false;
static const bool is_stable = heap_base_maker::is_stable;
static const bool has_reserve = true;
/**
* \b Effects: constructs an empty priority queue.
*
* \b Complexity: Constant.
*
* */
explicit priority_queue(value_compare const & cmp = value_compare()):
super_t(cmp)
{}
/**
* \b Effects: copy-constructs priority queue from rhs.
*
* \b Complexity: Linear.
*
* */
priority_queue (priority_queue const & rhs):
super_t(rhs), q_(rhs.q_)
{}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
/**
* \b Effects: C++11-style move constructor.
*
* \b Complexity: Constant.
*
* \b Note: Only available, if BOOST_NO_CXX11_RVALUE_REFERENCES is not defined
* */
priority_queue(priority_queue && rhs):
super_t(std::move(rhs)), q_(std::move(rhs.q_))
{}
/**
* \b Effects: C++11-style move assignment.
*
* \b Complexity: Constant.
*
* \b Note: Only available, if BOOST_NO_CXX11_RVALUE_REFERENCES is not defined
* */
priority_queue & operator=(priority_queue && rhs)
{
super_t::operator=(std::move(rhs));
q_ = std::move(rhs.q_);
return *this;
}
#endif
/**
* \b Effects: Assigns priority queue from rhs.
*
* \b Complexity: Linear.
*
* */
priority_queue & operator=(priority_queue const & rhs)
{
static_cast<super_t&>(*this) = static_cast<super_t const &>(rhs);
q_ = rhs.q_;
return *this;
}
/**
* \b Effects: Returns true, if the priority queue contains no elements.
*
* \b Complexity: Constant.
*
* */
bool empty(void) const
{
return q_.empty();
}
/**
* \b Effects: Returns the number of elements contained in the priority queue.
*
* \b Complexity: Constant.
*
* */
size_type size(void) const
{
return q_.size();
}
/**
* \b Effects: Returns the maximum number of elements the priority queue can contain.
*
* \b Complexity: Constant.
*
* */
size_type max_size(void) const
{
return q_.max_size();
}
/**
* \b Effects: Removes all elements from the priority queue.
*
* \b Complexity: Linear.
*
* */
void clear(void)
{
q_.clear();
}
/**
* \b Effects: Returns allocator.
*
* \b Complexity: Constant.
*
* */
allocator_type get_allocator(void) const
{
return q_.get_allocator();
}
/**
* \b Effects: Returns a const_reference to the maximum element.
*
* \b Complexity: Constant.
*
* */
const_reference top(void) const
{
BOOST_ASSERT(!empty());
return super_t::get_value(q_.front());
}
/**
* \b Effects: Adds a new element to the priority queue.
*
* \b Complexity: Logarithmic (amortized). Linear (worst case).
*
* */
void push(value_type const & v)
{
q_.push_back(super_t::make_node(v));
std::push_heap(q_.begin(), q_.end(), static_cast<super_t const &>(*this));
}
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
/**
* \b Effects: Adds a new element to the priority queue. The element is directly constructed in-place.
*
* \b Complexity: Logarithmic (amortized). Linear (worst case).
*
* */
template <class... Args>
void emplace(Args&&... args)
{
q_.emplace_back(super_t::make_node(std::forward<Args>(args)...));
std::push_heap(q_.begin(), q_.end(), static_cast<super_t const &>(*this));
}
#endif
/**
* \b Effects: Removes the top element from the priority queue.
*
* \b Complexity: Logarithmic (amortized). Linear (worst case).
*
* */
void pop(void)
{
BOOST_ASSERT(!empty());
std::pop_heap(q_.begin(), q_.end(), static_cast<super_t const &>(*this));
q_.pop_back();
}
/**
* \b Effects: Swaps two priority queues.
*
* \b Complexity: Constant.
*
* */
void swap(priority_queue & rhs)
{
super_t::swap(rhs);
q_.swap(rhs.q_);
}
/**
* \b Effects: Returns an iterator to the first element contained in the priority queue.
*
* \b Complexity: Constant.
*
* */
iterator begin(void) const
{
return iterator(q_.begin());
}
/**
* \b Effects: Returns an iterator to the end of the priority queue.
*
* \b Complexity: Constant.
*
* */
iterator end(void) const
{
return iterator(q_.end());
}
/**
* \b Effects: Reserves memory for element_count elements
*
* \b Complexity: Linear.
*
* \b Node: Invalidates iterators
*
* */
void reserve(size_type element_count)
{
q_.reserve(element_count);
}
/**
* \b Effect: Returns the value_compare object used by the priority queue
*
* */
value_compare const & value_comp(void) const
{
return super_t::value_comp();
}
/**
* \b Returns: Element-wise comparison of heap data structures
*
* \b Requirement: the \c value_compare object of both heaps must match.
*
* */
template <typename HeapType>
bool operator<(HeapType const & rhs) const
{
return detail::heap_compare(*this, rhs);
}
/**
* \b Returns: Element-wise comparison of heap data structures
*
* \b Requirement: the \c value_compare object of both heaps must match.
*
* */
template <typename HeapType>
bool operator>(HeapType const & rhs) const
{
return detail::heap_compare(rhs, *this);
}
/**
* \b Returns: Element-wise comparison of heap data structures
*
* \b Requirement: the \c value_compare object of both heaps must match.
*
* */
template <typename HeapType>
bool operator>=(HeapType const & rhs) const
{
return !operator<(rhs);
}
/**
* \b Returns: Element-wise comparison of heap data structures
*
* \b Requirement: the \c value_compare object of both heaps must match.
*
* */
template <typename HeapType>
bool operator<=(HeapType const & rhs) const
{
return !operator>(rhs);
}
/** \brief Equivalent comparison
* \b Returns: True, if both heap data structures are equivalent.
*
* \b Requirement: the \c value_compare object of both heaps must match.
*
* */
template <typename HeapType>
bool operator==(HeapType const & rhs) const
{
return detail::heap_equality(*this, rhs);
}
/** \brief Equivalent comparison
* \b Returns: True, if both heap data structures are not equivalent.
*
* \b Requirement: the \c value_compare object of both heaps must match.
*
* */
template <typename HeapType>
bool operator!=(HeapType const & rhs) const
{
return !(*this == rhs);
}
};
} /* namespace heap */
} /* namespace boost */
#endif /* BOOST_HEAP_PRIORITY_QUEUE_HPP */

View File

@@ -0,0 +1,925 @@
// boost heap: skew heap
//
// Copyright (C) 2010 Tim Blechmann
//
// 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_HEAP_SKEW_HEAP_HPP
#define BOOST_HEAP_SKEW_HEAP_HPP
#include <algorithm>
#include <utility>
#include <vector>
#include <boost/assert.hpp>
#include <boost/array.hpp>
#include <boost/heap/detail/heap_comparison.hpp>
#include <boost/heap/detail/heap_node.hpp>
#include <boost/heap/detail/stable_heap.hpp>
#include <boost/heap/detail/tree_iterator.hpp>
#ifndef BOOST_DOXYGEN_INVOKED
#ifdef BOOST_HEAP_SANITYCHECKS
#define BOOST_HEAP_ASSERT BOOST_ASSERT
#else
#define BOOST_HEAP_ASSERT(expression)
#endif
#endif
namespace boost {
namespace heap {
namespace detail {
template <typename node_pointer, bool store_parent_pointer>
struct parent_holder
{
parent_holder(void):
parent_(NULL)
{}
void set_parent(node_pointer parent)
{
BOOST_HEAP_ASSERT(static_cast<node_pointer>(this) != parent);
parent_ = parent;
}
node_pointer get_parent(void) const
{
return parent_;
}
node_pointer parent_;
};
template <typename node_pointer>
struct parent_holder<node_pointer, false>
{
void set_parent(node_pointer parent)
{}
node_pointer get_parent(void) const
{
return NULL;
}
};
template <typename value_type, bool store_parent_pointer>
struct skew_heap_node:
parent_holder<skew_heap_node<value_type, store_parent_pointer>*, store_parent_pointer>
{
typedef parent_holder<skew_heap_node<value_type, store_parent_pointer>*, store_parent_pointer> super_t;
typedef boost::array<skew_heap_node*, 2> child_list_type;
typedef typename child_list_type::iterator child_iterator;
typedef typename child_list_type::const_iterator const_child_iterator;
skew_heap_node(value_type const & v):
value(v)
{
children.assign(0);
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
skew_heap_node(value_type && v):
value(v)
{
children.assign(0);
}
#endif
template <typename Alloc>
skew_heap_node (skew_heap_node const & rhs, Alloc & allocator, skew_heap_node * parent):
value(rhs.value)
{
super_t::set_parent(parent);
node_cloner<skew_heap_node, skew_heap_node, Alloc> cloner(allocator);
clone_child(0, rhs, cloner);
clone_child(1, rhs, cloner);
}
template <typename Cloner>
void clone_child(int index, skew_heap_node const & rhs, Cloner & cloner)
{
if (rhs.children[index])
children[index] = cloner(*rhs.children[index], this);
else
children[index] = NULL;
}
template <typename Alloc>
void clear_subtree(Alloc & alloc)
{
node_disposer<skew_heap_node, skew_heap_node, Alloc> disposer(alloc);
dispose_child(children[0], disposer);
dispose_child(children[1], disposer);
}
template <typename Disposer>
void dispose_child(skew_heap_node * node, Disposer & disposer)
{
if (node)
disposer(node);
}
std::size_t count_children(void) const
{
size_t ret = 1;
if (children[0])
ret += children[0]->count_children();
if (children[1])
ret += children[1]->count_children();
return ret;
}
template <typename HeapBase>
bool is_heap(typename HeapBase::value_compare const & cmp) const
{
for (const_child_iterator it = children.begin(); it != children.end(); ++it) {
const skew_heap_node * child = *it;
if (child == NULL)
continue;
if (store_parent_pointer)
BOOST_HEAP_ASSERT(child->get_parent() == this);
if (cmp(HeapBase::get_value(value), HeapBase::get_value(child->value)) ||
!child->is_heap<HeapBase>(cmp))
return false;
}
return true;
}
value_type value;
boost::array<skew_heap_node*, 2> children;
};
typedef parameter::parameters<boost::parameter::optional<tag::allocator>,
boost::parameter::optional<tag::compare>,
boost::parameter::optional<tag::stable>,
boost::parameter::optional<tag::store_parent_pointer>,
boost::parameter::optional<tag::stability_counter_type>,
boost::parameter::optional<tag::constant_time_size>,
boost::parameter::optional<tag::mutable_>
> skew_heap_signature;
template <typename T, typename BoundArgs>
struct make_skew_heap_base
{
static const bool constant_time_size = parameter::binding<BoundArgs,
tag::constant_time_size,
boost::mpl::true_
>::type::value;
typedef typename make_heap_base<T, BoundArgs, constant_time_size>::type base_type;
typedef typename make_heap_base<T, BoundArgs, constant_time_size>::allocator_argument allocator_argument;
typedef typename make_heap_base<T, BoundArgs, constant_time_size>::compare_argument compare_argument;
static const bool is_mutable = extract_mutable<BoundArgs>::value;
static const bool store_parent_pointer = parameter::binding<BoundArgs,
tag::store_parent_pointer,
boost::mpl::false_>::type::value || is_mutable;
typedef skew_heap_node<typename base_type::internal_type, store_parent_pointer> node_type;
typedef typename allocator_argument::template rebind<node_type>::other allocator_type;
struct type:
base_type,
allocator_type
{
type(compare_argument const & arg):
base_type(arg)
{}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
type(type && rhs):
base_type(std::move(static_cast<base_type&>(rhs))),
allocator_type(std::move(static_cast<allocator_type&>(rhs)))
{}
type(type const & rhs):
base_type(rhs),
allocator_type(rhs)
{}
type & operator=(type && rhs)
{
base_type::operator=(std::move(static_cast<base_type&>(rhs)));
allocator_type::operator=(std::move(static_cast<allocator_type&>(rhs)));
return *this;
}
type & operator=(type const & rhs)
{
base_type::operator=(static_cast<base_type const &>(rhs));
allocator_type::operator=(static_cast<allocator_type const &>(rhs));
return *this;
}
#endif
};
};
} /* namespace detail */
/**
* \class skew_heap
* \brief skew heap
*
*
* The template parameter T is the type to be managed by the container.
* The user can specify additional options and if no options are provided default options are used.
*
* The container supports the following options:
* - \c boost::heap::compare<>, defaults to \c compare<std::less<T> >
* - \c boost::heap::stable<>, defaults to \c stable<false>
* - \c boost::heap::stability_counter_type<>, defaults to \c stability_counter_type<boost::uintmax_t>
* - \c boost::heap::allocator<>, defaults to \c allocator<std::allocator<T> >
* - \c boost::heap::constant_time_size<>, defaults to \c constant_time_size<true>
* - \c boost::heap::store_parent_pointer<>, defaults to \c store_parent_pointer<true>. Maintaining a parent pointer adds some
* maintenance and size overhead, but iterating a heap is more efficient.
* - \c boost::heap::mutable<>, defaults to \c mutable<false>.
*
*/
#ifdef BOOST_DOXYGEN_INVOKED
template<class T, class ...Options>
#else
template <typename T,
class A0 = boost::parameter::void_,
class A1 = boost::parameter::void_,
class A2 = boost::parameter::void_,
class A3 = boost::parameter::void_,
class A4 = boost::parameter::void_,
class A5 = boost::parameter::void_,
class A6 = boost::parameter::void_
>
#endif
class skew_heap:
private detail::make_skew_heap_base<T,
typename detail::skew_heap_signature::bind<A0, A1, A2, A3, A4, A5, A6>::type
>::type
{
typedef typename detail::skew_heap_signature::bind<A0, A1, A2, A3, A4, A5, A6>::type bound_args;
typedef detail::make_skew_heap_base<T, bound_args> base_maker;
typedef typename base_maker::type super_t;
typedef typename super_t::internal_type internal_type;
typedef typename super_t::size_holder_type size_holder;
typedef typename base_maker::allocator_argument allocator_argument;
static const bool store_parent_pointer = base_maker::store_parent_pointer;
template <typename Heap1, typename Heap2>
friend struct heap_merge_emulate;
struct implementation_defined:
detail::extract_allocator_types<typename base_maker::allocator_argument>
{
typedef T value_type;
typedef typename base_maker::compare_argument value_compare;
typedef typename base_maker::allocator_type allocator_type;
typedef typename base_maker::node_type node;
typedef typename allocator_type::pointer node_pointer;
typedef typename allocator_type::const_pointer const_node_pointer;
typedef detail::value_extractor<value_type, internal_type, super_t> value_extractor;
typedef boost::array<node_pointer, 2> child_list_type;
typedef typename child_list_type::iterator child_list_iterator;
typedef typename boost::mpl::if_c<false,
detail::recursive_tree_iterator<node,
child_list_iterator,
const value_type,
value_extractor,
detail::list_iterator_converter<node,
child_list_type
>
>,
detail::tree_iterator<node,
const value_type,
allocator_type,
value_extractor,
detail::dereferencer<node>,
true,
false,
value_compare
>
>::type iterator;
typedef iterator const_iterator;
typedef detail::tree_iterator<node,
const value_type,
allocator_type,
value_extractor,
detail::dereferencer<node>,
true,
true,
value_compare
> ordered_iterator;
typedef typename detail::extract_allocator_types<typename base_maker::allocator_argument>::reference reference;
typedef detail::node_handle<node_pointer, super_t, reference> handle_type;
};
typedef typename implementation_defined::value_extractor value_extractor;
typedef typename implementation_defined::node node;
typedef typename implementation_defined::node_pointer node_pointer;
public:
typedef T value_type;
typedef typename implementation_defined::size_type size_type;
typedef typename implementation_defined::difference_type difference_type;
typedef typename implementation_defined::value_compare value_compare;
typedef typename implementation_defined::allocator_type allocator_type;
typedef typename implementation_defined::reference reference;
typedef typename implementation_defined::const_reference const_reference;
typedef typename implementation_defined::pointer pointer;
typedef typename implementation_defined::const_pointer const_pointer;
/// \copydoc boost::heap::priority_queue::iterator
typedef typename implementation_defined::iterator iterator;
typedef typename implementation_defined::const_iterator const_iterator;
typedef typename implementation_defined::ordered_iterator ordered_iterator;
static const bool constant_time_size = super_t::constant_time_size;
static const bool has_ordered_iterators = true;
static const bool is_mergable = true;
static const bool is_stable = detail::extract_stable<bound_args>::value;
static const bool has_reserve = false;
static const bool is_mutable = detail::extract_mutable<bound_args>::value;
typedef typename mpl::if_c<is_mutable, typename implementation_defined::handle_type, void*>::type handle_type;
/// \copydoc boost::heap::priority_queue::priority_queue(value_compare const &)
explicit skew_heap(value_compare const & cmp = value_compare()):
super_t(cmp), root(NULL)
{}
/// \copydoc boost::heap::priority_queue::priority_queue(priority_queue const &)
skew_heap(skew_heap const & rhs):
super_t(rhs), root(0)
{
if (rhs.empty())
return;
clone_tree(rhs);
size_holder::set_size(rhs.get_size());
}
/// \copydoc boost::heap::priority_queue::operator=(priority_queue const & rhs)
skew_heap & operator=(skew_heap const & rhs)
{
clear();
size_holder::set_size(rhs.get_size());
static_cast<super_t&>(*this) = rhs;
clone_tree(rhs);
return *this;
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
/// \copydoc boost::heap::priority_queue::priority_queue(priority_queue &&)
skew_heap(skew_heap && rhs):
super_t(std::move(rhs)), root(rhs.root)
{
rhs.root = NULL;
}
/// \copydoc boost::heap::priority_queue::operator=(priority_queue &&)
skew_heap & operator=(skew_heap && rhs)
{
super_t::operator=(std::move(rhs));
root = rhs.root;
rhs.root = NULL;
return *this;
}
#endif
~skew_heap(void)
{
clear();
}
/**
* \b Effects: Adds a new element to the priority queue.
*
* \b Complexity: Logarithmic (amortized).
*
* */
typename mpl::if_c<is_mutable, handle_type, void>::type push(value_type const & v)
{
typedef typename mpl::if_c<is_mutable, push_handle, push_void>::type push_helper;
return push_helper::push(this, v);
}
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
/**
* \b Effects: Adds a new element to the priority queue. The element is directly constructed in-place.
*
* \b Complexity: Logarithmic (amortized).
*
* */
template <typename... Args>
typename mpl::if_c<is_mutable, handle_type, void>::type emplace(Args&&... args)
{
typedef typename mpl::if_c<is_mutable, push_handle, push_void>::type push_helper;
return push_helper::emplace(this, std::forward<Args>(args)...);
}
#endif
/// \copydoc boost::heap::priority_queue::empty
bool empty(void) const
{
return root == NULL;
}
/// \copydoc boost::heap::binomial_heap::size
size_type size(void) const
{
if (constant_time_size)
return size_holder::get_size();
if (root == NULL)
return 0;
else
return root->count_children();
}
/// \copydoc boost::heap::priority_queue::max_size
size_type max_size(void) const
{
return allocator_type::max_size();
}
/// \copydoc boost::heap::priority_queue::clear
void clear(void)
{
if (empty())
return;
root->template clear_subtree<allocator_type>(*this);
root->~node();
allocator_type::deallocate(root, 1);
root = NULL;
size_holder::set_size(0);
}
/// \copydoc boost::heap::priority_queue::get_allocator
allocator_type get_allocator(void) const
{
return *this;
}
/// \copydoc boost::heap::priority_queue::swap
void swap(skew_heap & rhs)
{
super_t::swap(rhs);
std::swap(root, rhs.root);
}
/// \copydoc boost::heap::priority_queue::top
const_reference top(void) const
{
BOOST_ASSERT(!empty());
return super_t::get_value(root->value);
}
/**
* \b Effects: Removes the top element from the priority queue.
*
* \b Complexity: Logarithmic (amortized).
*
* */
void pop(void)
{
BOOST_ASSERT(!empty());
node_pointer top = root;
root = merge_children(root);
size_holder::decrement();
if (root)
BOOST_HEAP_ASSERT(root->get_parent() == NULL);
else
BOOST_HEAP_ASSERT(size_holder::get_size() == 0);
top->~node();
allocator_type::deallocate(top, 1);
sanity_check();
}
/// \copydoc boost::heap::priority_queue::begin
iterator begin(void) const
{
return iterator(root, super_t::value_comp());
}
/// \copydoc boost::heap::priority_queue::end
iterator end(void) const
{
return iterator();
}
/// \copydoc boost::heap::fibonacci_heap::ordered_begin
ordered_iterator ordered_begin(void) const
{
return ordered_iterator(root, super_t::value_comp());
}
/// \copydoc boost::heap::fibonacci_heap::ordered_begin
ordered_iterator ordered_end(void) const
{
return ordered_iterator(0, super_t::value_comp());
}
/**
* \b Effects: Merge all elements from rhs into this
*
* \b Complexity: Logarithmic (amortized).
*
* */
void merge(skew_heap & rhs)
{
if (rhs.empty())
return;
merge_node(rhs.root);
size_holder::add(rhs.get_size());
rhs.set_size(0);
rhs.root = NULL;
sanity_check();
super_t::set_stability_count((std::max)(super_t::get_stability_count(),
rhs.get_stability_count()));
rhs.set_stability_count(0);
}
/// \copydoc boost::heap::priority_queue::value_comp
value_compare const & value_comp(void) const
{
return super_t::value_comp();
}
/// \copydoc boost::heap::priority_queue::operator<(HeapType const & rhs) const
template <typename HeapType>
bool operator<(HeapType const & rhs) const
{
return detail::heap_compare(*this, rhs);
}
/// \copydoc boost::heap::priority_queue::operator>(HeapType const & rhs) const
template <typename HeapType>
bool operator>(HeapType const & rhs) const
{
return detail::heap_compare(rhs, *this);
}
/// \copydoc boost::heap::priority_queue::operator>=(HeapType const & rhs) const
template <typename HeapType>
bool operator>=(HeapType const & rhs) const
{
return !operator<(rhs);
}
/// \copydoc boost::heap::priority_queue::operator<=(HeapType const & rhs) const
template <typename HeapType>
bool operator<=(HeapType const & rhs) const
{
return !operator>(rhs);
}
/// \copydoc boost::heap::priority_queue::operator==(HeapType const & rhs) const
template <typename HeapType>
bool operator==(HeapType const & rhs) const
{
return detail::heap_equality(*this, rhs);
}
/// \copydoc boost::heap::priority_queue::operator!=(HeapType const & rhs) const
template <typename HeapType>
bool operator!=(HeapType const & rhs) const
{
return !(*this == rhs);
}
/// \copydoc boost::heap::d_ary_heap::s_handle_from_iterator
static handle_type s_handle_from_iterator(iterator const & it)
{
node * ptr = const_cast<node *>(it.get_node());
return handle_type(ptr);
}
/**
* \b Effects: Removes the element handled by \c handle from the priority_queue.
*
* \b Complexity: Logarithmic (amortized).
* */
void erase (handle_type object)
{
BOOST_STATIC_ASSERT(is_mutable);
node_pointer this_node = object.node_;
unlink_node(this_node);
size_holder::decrement();
sanity_check();
this_node->~node();
allocator_type::deallocate(this_node, 1);
}
/**
* \b Effects: Assigns \c v to the element handled by \c handle & updates the priority queue.
*
* \b Complexity: Logarithmic (amortized).
*
* */
void update (handle_type handle, const_reference v)
{
BOOST_STATIC_ASSERT(is_mutable);
if (super_t::operator()(super_t::get_value(handle.node_->value), v))
increase(handle, v);
else
decrease(handle, v);
}
/**
* \b Effects: Updates the heap after the element handled by \c handle has been changed.
*
* \b Complexity: Logarithmic (amortized).
*
* \b Note: If this is not called, after a handle has been updated, the behavior of the data structure is undefined!
* */
void update (handle_type handle)
{
BOOST_STATIC_ASSERT(is_mutable);
node_pointer this_node = handle.node_;
if (this_node->get_parent()) {
if (super_t::operator()(super_t::get_value(this_node->get_parent()->value),
super_t::get_value(this_node->value)))
increase(handle);
else
decrease(handle);
}
else
decrease(handle);
}
/**
* \b Effects: Assigns \c v to the element handled by \c handle & updates the priority queue.
*
* \b Complexity: Logarithmic (amortized).
*
* \b Note: The new value is expected to be greater than the current one
* */
void increase (handle_type handle, const_reference v)
{
BOOST_STATIC_ASSERT(is_mutable);
handle.node_->value = super_t::make_node(v);
increase(handle);
}
/**
* \b Effects: Updates the heap after the element handled by \c handle has been changed.
*
* \b Complexity: Logarithmic (amortized).
*
* \b Note: If this is not called, after a handle has been updated, the behavior of the data structure is undefined!
* */
void increase (handle_type handle)
{
BOOST_STATIC_ASSERT(is_mutable);
node_pointer this_node = handle.node_;
if (this_node == root)
return;
node_pointer parent = this_node->get_parent();
if (this_node == parent->children[0])
parent->children[0] = NULL;
else
parent->children[1] = NULL;
this_node->set_parent(NULL);
merge_node(this_node);
}
/**
* \b Effects: Assigns \c v to the element handled by \c handle & updates the priority queue.
*
* \b Complexity: Logarithmic (amortized).
*
* \b Note: The new value is expected to be less than the current one
* */
void decrease (handle_type handle, const_reference v)
{
BOOST_STATIC_ASSERT(is_mutable);
handle.node_->value = super_t::make_node(v);
decrease(handle);
}
/**
* \b Effects: Updates the heap after the element handled by \c handle has been changed.
*
* \b Complexity: Logarithmic (amortized).
*
* \b Note: The new value is expected to be less than the current one. If this is not called, after a handle has been updated, the behavior of the data structure is undefined!
* */
void decrease (handle_type handle)
{
BOOST_STATIC_ASSERT(is_mutable);
node_pointer this_node = handle.node_;
unlink_node(this_node);
this_node->children.assign(0);
this_node->set_parent(NULL);
merge_node(this_node);
}
private:
#if !defined(BOOST_DOXYGEN_INVOKED)
struct push_void
{
static void push(skew_heap * self, const_reference v)
{
self->push_internal(v);
}
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class... Args>
static void emplace(skew_heap * self, Args&&... args)
{
self->emplace_internal(std::forward<Args>(args)...);
}
#endif
};
struct push_handle
{
static handle_type push(skew_heap * self, const_reference v)
{
return handle_type(self->push_internal(v));
}
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class... Args>
static handle_type emplace(skew_heap * self, Args&&... args)
{
return handle_type(self->emplace_internal(std::forward<Args>(args)...));
}
#endif
};
node_pointer push_internal(const_reference v)
{
size_holder::increment();
node_pointer n = super_t::allocate(1);
new(n) node(super_t::make_node(v));
merge_node(n);
return n;
}
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
template <class... Args>
node_pointer emplace_internal(Args&&... args)
{
size_holder::increment();
node_pointer n = super_t::allocate(1);
new(n) node(super_t::make_node(std::forward<Args>(args)...));
merge_node(n);
return n;
}
#endif
void unlink_node(node_pointer node)
{
node_pointer parent = node->get_parent();
node_pointer merged_children = merge_children(node);
if (parent) {
if (node == parent->children[0])
parent->children[0] = merged_children;
else
parent->children[1] = merged_children;
}
else
root = merged_children;
}
void clone_tree(skew_heap const & rhs)
{
BOOST_HEAP_ASSERT(root == NULL);
if (rhs.empty())
return;
root = allocator_type::allocate(1);
new(root) node(*rhs.root, static_cast<allocator_type&>(*this), NULL);
}
void merge_node(node_pointer other)
{
BOOST_HEAP_ASSERT(other);
if (root != NULL)
root = merge_nodes(root, other, NULL);
else
root = other;
}
node_pointer merge_nodes(node_pointer node1, node_pointer node2, node_pointer new_parent)
{
if (node1 == NULL) {
if (node2)
node2->set_parent(new_parent);
return node2;
}
if (node2 == NULL) {
node1->set_parent(new_parent);
return node1;
}
node_pointer merged = merge_nodes_recursive(node1, node2, new_parent);
return merged;
}
node_pointer merge_children(node_pointer node)
{
node_pointer parent = node->get_parent();
node_pointer merged_children = merge_nodes(node->children[0], node->children[1], parent);
return merged_children;
}
node_pointer merge_nodes_recursive(node_pointer node1, node_pointer node2, node_pointer new_parent)
{
if (super_t::operator()(node1->value, node2->value))
std::swap(node1, node2);
node * parent = node1;
node * child = node2;
if (parent->children[1]) {
node * merged = merge_nodes(parent->children[1], child, parent);
parent->children[1] = merged;
merged->set_parent(parent);
} else {
parent->children[1] = child;
child->set_parent(parent);
}
std::swap(parent->children[0], parent->children[1]);
parent->set_parent(new_parent);
return parent;
}
void sanity_check(void)
{
#ifdef BOOST_HEAP_SANITYCHECKS
if (root)
BOOST_HEAP_ASSERT( root->template is_heap<super_t>(super_t::value_comp()) );
if (constant_time_size) {
size_type stored_size = size_holder::get_size();
size_type counted_size;
if (root == NULL)
counted_size = 0;
else
counted_size = root->count_children();
BOOST_HEAP_ASSERT(counted_size == stored_size);
}
#endif
}
node_pointer root;
#endif
};
} /* namespace heap */
} /* namespace boost */
#undef BOOST_HEAP_ASSERT
#endif /* BOOST_HEAP_SKEW_HEAP_HPP */