kpeter@750: /* -*- mode: C++; indent-tabs-mode: nil; -*- kpeter@748: * kpeter@750: * This file is a part of LEMON, a generic C++ optimization library. kpeter@748: * kpeter@750: * Copyright (C) 2003-2009 kpeter@748: * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport kpeter@748: * (Egervary Research Group on Combinatorial Optimization, EGRES). kpeter@748: * kpeter@748: * Permission to use, modify and distribute this software is granted kpeter@748: * provided that this copyright notice appears in all copies. For kpeter@748: * precise terms see the accompanying LICENSE file. kpeter@748: * kpeter@748: * This software is provided "AS IS" with no warranty of any kind, kpeter@748: * express or implied, and with no claim as to its suitability for any kpeter@748: * purpose. kpeter@748: * kpeter@748: */ kpeter@748: kpeter@748: #ifndef LEMON_FOURARY_HEAP_H kpeter@748: #define LEMON_FOURARY_HEAP_H kpeter@748: kpeter@750: ///\ingroup heaps kpeter@748: ///\file kpeter@750: ///\brief Fourary heap implementation. kpeter@748: kpeter@748: #include kpeter@748: #include kpeter@748: #include kpeter@748: kpeter@748: namespace lemon { kpeter@748: kpeter@750: /// \ingroup heaps kpeter@748: /// kpeter@750: ///\brief Fourary heap data structure. kpeter@748: /// kpeter@750: /// This class implements the \e fourary \e heap data structure. kpeter@750: /// It fully conforms to the \ref concepts::Heap "heap concept". kpeter@748: /// kpeter@750: /// The fourary heap is a specialization of the \ref KaryHeap "K-ary heap" kpeter@750: /// for K=4. It is similar to the \ref BinHeap "binary heap", kpeter@750: /// but its nodes have at most four children, instead of two. kpeter@748: /// kpeter@750: /// \tparam PR Type of the priorities of the items. kpeter@750: /// \tparam IM A read-writable item map with \c int values, used kpeter@750: /// internally to handle the cross references. kpeter@750: /// \tparam CMP A functor class for comparing the priorities. kpeter@750: /// The default is \c std::less. kpeter@750: /// kpeter@750: ///\sa BinHeap kpeter@750: ///\sa KaryHeap kpeter@750: #ifdef DOXYGEN kpeter@750: template kpeter@750: #else kpeter@750: template > kpeter@750: #endif kpeter@750: class FouraryHeap { kpeter@750: public: kpeter@750: /// Type of the item-int map. kpeter@750: typedef IM ItemIntMap; kpeter@750: /// Type of the priorities. kpeter@750: typedef PR Prio; kpeter@750: /// Type of the items stored in the heap. kpeter@750: typedef typename ItemIntMap::Key Item; kpeter@750: /// Type of the item-priority pairs. kpeter@750: typedef std::pair Pair; kpeter@750: /// Functor type for comparing the priorities. kpeter@750: typedef CMP Compare; kpeter@748: kpeter@750: /// \brief Type to represent the states of the items. kpeter@748: /// kpeter@750: /// Each item has a state associated to it. It can be "in heap", kpeter@750: /// "pre-heap" or "post-heap". The latter two are indifferent from the kpeter@748: /// heap's point of view, but may be useful to the user. kpeter@748: /// kpeter@750: /// The item-int map must be initialized in such way that it assigns kpeter@750: /// \c PRE_HEAP (-1) to any element to be put in the heap. kpeter@748: enum State { kpeter@750: IN_HEAP = 0, ///< = 0. kpeter@750: PRE_HEAP = -1, ///< = -1. kpeter@750: POST_HEAP = -2 ///< = -2. kpeter@748: }; kpeter@748: kpeter@748: private: kpeter@750: std::vector _data; kpeter@750: Compare _comp; kpeter@750: ItemIntMap &_iim; kpeter@748: kpeter@748: public: kpeter@750: /// \brief Constructor. kpeter@748: /// kpeter@750: /// Constructor. kpeter@750: /// \param map A map that assigns \c int values to the items. kpeter@750: /// It is used internally to handle the cross references. kpeter@750: /// The assigned value must be \c PRE_HEAP (-1) for each item. kpeter@750: explicit FouraryHeap(ItemIntMap &map) : _iim(map) {} kpeter@748: kpeter@750: /// \brief Constructor. kpeter@748: /// kpeter@750: /// Constructor. kpeter@750: /// \param map A map that assigns \c int values to the items. kpeter@750: /// It is used internally to handle the cross references. kpeter@750: /// The assigned value must be \c PRE_HEAP (-1) for each item. kpeter@750: /// \param comp The function object used for comparing the priorities. kpeter@750: FouraryHeap(ItemIntMap &map, const Compare &comp) kpeter@750: : _iim(map), _comp(comp) {} kpeter@750: kpeter@750: /// \brief The number of items stored in the heap. kpeter@748: /// kpeter@750: /// This function returns the number of items stored in the heap. kpeter@750: int size() const { return _data.size(); } kpeter@748: kpeter@750: /// \brief Check if the heap is empty. kpeter@748: /// kpeter@750: /// This function returns \c true if the heap is empty. kpeter@750: bool empty() const { return _data.empty(); } kpeter@748: kpeter@750: /// \brief Make the heap empty. kpeter@748: /// kpeter@750: /// This functon makes the heap empty. kpeter@750: /// It does not change the cross reference map. If you want to reuse kpeter@750: /// a heap that is not surely empty, you should first clear it and kpeter@750: /// then you should set the cross reference map to \c PRE_HEAP kpeter@750: /// for each item. kpeter@750: void clear() { _data.clear(); } kpeter@748: kpeter@748: private: kpeter@748: static int parent(int i) { return (i-1)/4; } kpeter@748: static int firstChild(int i) { return 4*i+1; } kpeter@748: kpeter@748: bool less(const Pair &p1, const Pair &p2) const { kpeter@750: return _comp(p1.second, p2.second); kpeter@748: } kpeter@748: kpeter@750: void bubbleUp(int hole, Pair p) { kpeter@748: int par = parent(hole); kpeter@750: while( hole>0 && less(p,_data[par]) ) { kpeter@750: move(_data[par],hole); kpeter@748: hole = par; kpeter@748: par = parent(hole); kpeter@748: } kpeter@748: move(p, hole); kpeter@748: } kpeter@748: kpeter@750: void bubbleDown(int hole, Pair p, int length) { kpeter@752: if( length>1 ) { kpeter@752: int child = firstChild(hole); kpeter@753: while( child+30) bubbleDown(0, _data[n], n); kpeter@750: _data.pop_back(); kpeter@748: } kpeter@748: kpeter@750: /// \brief Remove the given item from the heap. kpeter@748: /// kpeter@750: /// This function removes the given item from the heap if it is kpeter@750: /// already stored. kpeter@750: /// \param i The item to delete. kpeter@750: /// \pre \e i must be in the heap. kpeter@748: void erase(const Item &i) { kpeter@750: int h = _iim[i]; kpeter@750: int n = _data.size()-1; kpeter@750: _iim.set(_data[h].first, POST_HEAP); kpeter@748: if( h=0) s=0; kpeter@748: return State(s); kpeter@748: } kpeter@748: kpeter@750: /// \brief Set the state of an item in the heap. kpeter@748: /// kpeter@750: /// This function sets the state of the given item in the heap. kpeter@750: /// It can be used to manually clear the heap when it is important kpeter@750: /// to achive better time complexity. kpeter@748: /// \param i The item. kpeter@748: /// \param st The state. It should not be \c IN_HEAP. kpeter@748: void state(const Item& i, State st) { kpeter@748: switch (st) { kpeter@748: case POST_HEAP: kpeter@748: case PRE_HEAP: kpeter@748: if (state(i) == IN_HEAP) erase(i); kpeter@750: _iim[i] = st; kpeter@748: break; kpeter@748: case IN_HEAP: kpeter@748: break; kpeter@748: } kpeter@748: } kpeter@748: kpeter@750: /// \brief Replace an item in the heap. kpeter@748: /// kpeter@750: /// This function replaces item \c i with item \c j. kpeter@750: /// Item \c i must be in the heap, while \c j must be out of the heap. kpeter@750: /// After calling this method, item \c i will be out of the kpeter@750: /// heap and \c j will be in the heap with the same prioriority kpeter@750: /// as item \c i had before. kpeter@748: void replace(const Item& i, const Item& j) { kpeter@750: int idx = _iim[i]; kpeter@750: _iim.set(i, _iim[j]); kpeter@750: _iim.set(j, idx); kpeter@750: _data[idx].first = j; kpeter@748: } kpeter@748: kpeter@748: }; // class FouraryHeap kpeter@748: kpeter@748: } // namespace lemon kpeter@748: kpeter@748: #endif // LEMON_FOURARY_HEAP_H