first commit
This commit is contained in:
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
Reference in New Issue
Block a user