| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390 | // 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/type_traits/conditional.hpp>#ifdef BOOST_HEAP_SANITYCHECKS#define BOOST_HEAP_ASSERT BOOST_ASSERT#else#define BOOST_HEAP_ASSERT(expression)#endifnamespace boost  {namespace heap   {namespace detail {namespace bi = boost::intrusive;template <bool auto_unlink = false>struct heap_node_base:    bi::list_base_hook<typename boost::conditional<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{#ifndef BOOST_NO_CXX11_ALLOCATOR    typedef std::allocator_traits<Alloc> allocator_traits;#endif    node_cloner(Alloc & allocator):        allocator(allocator)    {}    Node * operator() (NodeBase const & node)    {#ifdef BOOST_NO_CXX11_ALLOCATOR        Node * ret = allocator.allocate(1);        new (ret) Node(static_cast<Node const &>(node), allocator);#else        Node * ret = allocator_traits::allocate(allocator, 1);        allocator_traits::construct(allocator, ret, static_cast<Node const &>(node), allocator);#endif        return ret;    }    Node * operator() (NodeBase const & node, Node * parent)    {#ifdef BOOST_NO_CXX11_ALLOCATOR        Node * ret = allocator.allocate(1);        new (ret) Node(static_cast<Node const &>(node), allocator, parent);#else        Node * ret = allocator_traits::allocate(allocator, 1);        allocator_traits::construct(allocator, ret, static_cast<Node const &>(node), allocator, parent);#endif        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{#ifdef BOOST_NO_CXX11_ALLOCATOR    typedef typename Alloc::pointer node_pointer;#else    typedef std::allocator_traits<Alloc> allocator_traits;    typedef typename allocator_traits::pointer node_pointer;#endif    node_disposer(Alloc & alloc):        alloc_(alloc)    {}    void operator()(NodeBase * base)    {        node_pointer n = static_cast<node_pointer>(base);        n->clear_subtree(alloc_);#ifdef BOOST_NO_CXX11_ALLOCATOR        alloc_.destroy(n);        alloc_.deallocate(n, 1);#else        allocator_traits::destroy(alloc_, n);        allocator_traits::deallocate(alloc_, n, 1);#endif    }    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 */
 |