kpeter@748: /* -*- C++ -*- kpeter@748: * kpeter@748: * This file is a part of LEMON, a generic C++ optimization library kpeter@748: * kpeter@748: * Copyright (C) 2003-2008 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_KARY_HEAP_H kpeter@748: #define LEMON_KARY_HEAP_H kpeter@748: kpeter@748: ///\ingroup auxdat kpeter@748: ///\file kpeter@748: ///\brief Kary Heap implementation. kpeter@748: kpeter@748: #include kpeter@748: #include kpeter@748: #include kpeter@748: #include kpeter@748: kpeter@748: namespace lemon { kpeter@748: kpeter@748: ///\ingroup auxdat kpeter@748: /// kpeter@748: ///\brief A Kary Heap implementation. kpeter@748: /// kpeter@748: ///This class implements the \e Kary \e heap data structure. A \e heap kpeter@748: ///is a data structure for storing items with specified values called \e kpeter@748: ///priorities in such a way that finding the item with minimum priority is kpeter@748: ///efficient. \c Compare specifies the ordering of the priorities. In a heap kpeter@748: ///one can change the priority of an item, add or erase an item, etc. kpeter@748: /// kpeter@748: ///\param _Prio Type of the priority of the items. kpeter@748: ///\param _ItemIntMap A read and writable Item int map, used internally kpeter@748: ///to handle the cross references. kpeter@748: ///\param _Compare A class for the ordering of the priorities. The kpeter@748: ///default is \c std::less<_Prio>. kpeter@748: /// kpeter@748: ///\sa FibHeap kpeter@748: ///\sa Dijkstra kpeter@748: ///\author Dorian Batha kpeter@748: kpeter@748: template > kpeter@748: kpeter@748: class KaryHeap { kpeter@748: kpeter@748: public: kpeter@748: ///\e kpeter@748: typedef _ItemIntMap ItemIntMap; kpeter@748: ///\e kpeter@748: typedef _Prio Prio; kpeter@748: ///\e kpeter@748: typedef typename ItemIntMap::Key Item; kpeter@748: ///\e kpeter@748: typedef std::pair Pair; kpeter@748: ///\e kpeter@748: typedef _Compare Compare; kpeter@748: ///\e kpeter@748: kpeter@748: /// \brief Type to represent the items states. kpeter@748: /// kpeter@748: /// Each Item element have a state associated to it. It may be "in heap", kpeter@748: /// "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@748: /// The ItemIntMap \e should be initialized in such way that it maps kpeter@748: /// PRE_HEAP (-1) to any element to be put in the heap... kpeter@748: enum State { kpeter@748: IN_HEAP = 0, kpeter@748: PRE_HEAP = -1, kpeter@748: POST_HEAP = -2 kpeter@748: }; kpeter@748: kpeter@748: private: kpeter@748: std::vector data; kpeter@748: Compare comp; kpeter@748: ItemIntMap &iim; kpeter@748: int K; kpeter@748: kpeter@748: public: kpeter@748: /// \brief The constructor. kpeter@748: /// kpeter@748: /// The constructor. kpeter@748: /// \param _iim should be given to the constructor, since it is used kpeter@748: /// internally to handle the cross references. The value of the map kpeter@748: /// should be PRE_HEAP (-1) for each element. kpeter@748: explicit KaryHeap(ItemIntMap &_iim, const int &_K=32) : iim(_iim), K(_K) {} kpeter@748: kpeter@748: /// \brief The constructor. kpeter@748: /// kpeter@748: /// The constructor. kpeter@748: /// \param _iim should be given to the constructor, since it is used kpeter@748: /// internally to handle the cross references. The value of the map kpeter@748: /// should be PRE_HEAP (-1) for each element. kpeter@748: /// kpeter@748: /// \param _comp The comparator function object. kpeter@748: KaryHeap(ItemIntMap &_iim, const Compare &_comp, const int &_K=32) kpeter@748: : iim(_iim), comp(_comp), K(_K) {} kpeter@748: kpeter@748: kpeter@748: /// The number of items stored in the heap. kpeter@748: /// kpeter@748: /// \brief Returns the number of items stored in the heap. kpeter@748: int size() const { return data.size(); } kpeter@748: kpeter@748: /// \brief Checks if the heap stores no items. kpeter@748: /// kpeter@748: /// Returns \c true if and only if the heap stores no items. kpeter@748: bool empty() const { return data.empty(); } kpeter@748: kpeter@748: /// \brief Make empty this heap. kpeter@748: /// kpeter@748: /// Make empty this heap. It does not change the cross reference map. kpeter@748: /// If you want to reuse what is not surely empty you should first clear kpeter@748: /// the heap and after that you should set the cross reference map for kpeter@748: /// each item to \c PRE_HEAP. kpeter@748: void clear() { data.clear(); } kpeter@748: kpeter@748: private: kpeter@748: int parent(int i) { return (i-1)/K; } kpeter@748: int first_child(int i) { return K*i+1; } kpeter@748: kpeter@748: bool less(const Pair &p1, const Pair &p2) const { kpeter@748: return comp(p1.second, p2.second); kpeter@748: } kpeter@748: kpeter@748: int find_min(const int child, const int length) { kpeter@748: int min=child, i=1; kpeter@748: while( i0 && less(p,data[par]) ) { kpeter@748: 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@748: void bubble_down(int hole, Pair p, int length) { kpeter@748: if( length>1 ) { kpeter@748: int child = first_child(hole); kpeter@748: while( child0) bubble_down(0, data[n], n); kpeter@748: data.pop_back(); kpeter@748: } kpeter@748: kpeter@748: /// \brief Deletes \c i from the heap. kpeter@748: /// kpeter@748: /// This method deletes item \c i from the heap. kpeter@748: /// \param i The item to erase. kpeter@748: /// \pre The item should be in the heap. kpeter@748: void erase(const Item &i) { kpeter@748: int h = iim[i]; kpeter@748: int n = data.size()-1; kpeter@748: iim.set(data[h].first, POST_HEAP); kpeter@748: if( h=0) s=0; kpeter@748: return State(s); kpeter@748: } kpeter@748: kpeter@748: /// \brief Sets the state of the \c item in the heap. kpeter@748: /// kpeter@748: /// Sets the state of the \c item in the heap. It can be used to kpeter@748: /// manually clear the heap when it is important to achive the kpeter@748: /// 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@748: iim[i] = st; kpeter@748: break; kpeter@748: case IN_HEAP: kpeter@748: break; kpeter@748: } kpeter@748: } kpeter@748: kpeter@748: /// \brief Replaces an item in the heap. kpeter@748: /// kpeter@748: /// The \c i item is replaced with \c j item. The \c i item should kpeter@748: /// be in the heap, while the \c j should be out of the heap. The kpeter@748: /// \c i item will out of the heap and \c j will be in the heap kpeter@748: /// with the same prioriority as prevoiusly the \c i item. kpeter@748: void replace(const Item& i, const Item& j) { kpeter@748: int idx=iim[i]; kpeter@748: iim.set(i, iim[j]); kpeter@748: iim.set(j, idx); kpeter@748: data[idx].first=j; kpeter@748: } kpeter@748: kpeter@748: }; // class KaryHeap kpeter@748: kpeter@748: } // namespace lemon kpeter@748: kpeter@748: #endif // LEMON_KARY_HEAP_H