| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752 | // 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>#include <boost/type_traits/integral_constant.hpp>#ifdef BOOST_HAS_PRAGMA_ONCE#pragma once#endif#ifndef BOOST_DOXYGEN_INVOKED#ifdef BOOST_HEAP_SANITYCHECKS#define BOOST_HEAP_ASSERT BOOST_ASSERT#else#define BOOST_HEAP_ASSERT(expression)#endif#endifnamespace 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::true_type                                                             >::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;#ifdef BOOST_NO_CXX11_ALLOCATOR    typedef typename allocator_argument::template rebind<node_type>::other allocator_type;#else    typedef typename std::allocator_traits<allocator_argument>::template rebind_alloc<node_type> allocator_type;#endif    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_INVOKEDtemplate<class T, class ...Options>#elsetemplate <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_         >#endifclass 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;#ifdef BOOST_NO_CXX11_ALLOCATOR        typedef typename allocator_type::pointer node_pointer;        typedef typename allocator_type::const_pointer const_node_pointer;#else        typedef std::allocator_traits<allocator_type> allocator_traits;        typedef typename allocator_traits::pointer node_pointer;        typedef typename allocator_traits::const_pointer const_node_pointer;#endif        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;#endifpublic:    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;#ifndef BOOST_NO_CXX11_ALLOCATOR    typedef typename implementation_defined::allocator_traits allocator_traits;#endif    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    {#ifdef BOOST_NO_CXX11_ALLOCATOR        return allocator_type::max_size();#else        const allocator_type& alloc = *this;        return allocator_traits::max_size(alloc);#endif    }    /// \copydoc boost::heap::priority_queue::clear    void clear(void)    {        if (empty())            return;        root->template clear_subtree<allocator_type>(*this);#ifdef BOOST_NO_CXX11_ALLOCATOR        root->~node();        allocator_type::deallocate(root, 1);#else        allocator_type& alloc = *this;        allocator_traits::destroy(alloc, root);        allocator_traits::deallocate(alloc, root, 1);#endif        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();#ifdef BOOST_NO_CXX11_ALLOCATOR        node_pointer n = allocator_type::allocate(1);        new(n) node(super_t::make_node(v));#else        allocator_type& alloc = *this;        node_pointer n = allocator_traits::allocate(alloc, 1);        allocator_traits::construct(alloc, n, super_t::make_node(v));#endif        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();#ifdef BOOST_NO_CXX11_ALLOCATOR        node_pointer n = allocator_type::allocate(1);        new(n) node(super_t::make_node(std::forward<Args>(args)...));#else        allocator_type& alloc = *this;        node_pointer n = allocator_traits::allocate(alloc, 1);        allocator_traits::construct(alloc, n, super_t::make_node(std::forward<Args>(args)...));#endif        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();#ifdef BOOST_NO_CXX11_ALLOCATOR        n->~node();        allocator_type::deallocate(n, 1);#else        allocator_type& alloc = *this;        allocator_traits::destroy(alloc, n);        allocator_traits::deallocate(alloc, n, 1);#endif    }    /// \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(super_t::value_comp());    }    /// \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 */
 |