kpeter@701: /* -*- C++ -*- kpeter@701: * kpeter@701: * This file is a part of LEMON, a generic C++ optimization library kpeter@701: * kpeter@701: * Copyright (C) 2003-2008 kpeter@701: * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport kpeter@701: * (Egervary Research Group on Combinatorial Optimization, EGRES). kpeter@701: * kpeter@701: * Permission to use, modify and distribute this software is granted kpeter@701: * provided that this copyright notice appears in all copies. For kpeter@701: * precise terms see the accompanying LICENSE file. kpeter@701: * kpeter@701: * This software is provided "AS IS" with no warranty of any kind, kpeter@701: * express or implied, and with no claim as to its suitability for any kpeter@701: * purpose. kpeter@701: * kpeter@701: */ kpeter@701: kpeter@701: #ifndef LEMON_KARY_HEAP_H kpeter@701: #define LEMON_KARY_HEAP_H kpeter@701: kpeter@701: ///\ingroup auxdat kpeter@701: ///\file kpeter@701: ///\brief Kary Heap implementation. kpeter@701: kpeter@701: #include kpeter@701: #include kpeter@701: #include kpeter@701: #include kpeter@701: kpeter@701: namespace lemon { kpeter@701: kpeter@701: ///\ingroup auxdat kpeter@701: /// kpeter@701: ///\brief A Kary Heap implementation. kpeter@701: /// kpeter@701: ///This class implements the \e Kary \e heap data structure. A \e heap kpeter@701: ///is a data structure for storing items with specified values called \e kpeter@701: ///priorities in such a way that finding the item with minimum priority is kpeter@701: ///efficient. \c Compare specifies the ordering of the priorities. In a heap kpeter@701: ///one can change the priority of an item, add or erase an item, etc. kpeter@701: /// kpeter@701: ///\param _Prio Type of the priority of the items. kpeter@701: ///\param _ItemIntMap A read and writable Item int map, used internally kpeter@701: ///to handle the cross references. kpeter@701: ///\param _Compare A class for the ordering of the priorities. The kpeter@701: ///default is \c std::less<_Prio>. kpeter@701: /// kpeter@701: ///\sa FibHeap kpeter@701: ///\sa Dijkstra kpeter@701: ///\author Dorian Batha kpeter@701: kpeter@701: template > kpeter@701: kpeter@701: class KaryHeap { kpeter@701: kpeter@701: public: kpeter@701: ///\e kpeter@701: typedef _ItemIntMap ItemIntMap; kpeter@701: ///\e kpeter@701: typedef _Prio Prio; kpeter@701: ///\e kpeter@701: typedef typename ItemIntMap::Key Item; kpeter@701: ///\e kpeter@701: typedef std::pair Pair; kpeter@701: ///\e kpeter@701: typedef _Compare Compare; kpeter@701: ///\e kpeter@701: kpeter@701: /// \brief Type to represent the items states. kpeter@701: /// kpeter@701: /// Each Item element have a state associated to it. It may be "in heap", kpeter@701: /// "pre heap" or "post heap". The latter two are indifferent from the kpeter@701: /// heap's point of view, but may be useful to the user. kpeter@701: /// kpeter@701: /// The ItemIntMap \e should be initialized in such way that it maps kpeter@701: /// PRE_HEAP (-1) to any element to be put in the heap... kpeter@701: enum State { kpeter@701: IN_HEAP = 0, kpeter@701: PRE_HEAP = -1, kpeter@701: POST_HEAP = -2 kpeter@701: }; kpeter@701: kpeter@701: private: kpeter@701: std::vector data; kpeter@701: Compare comp; kpeter@701: ItemIntMap &iim; kpeter@701: int K; kpeter@701: kpeter@701: public: kpeter@701: /// \brief The constructor. kpeter@701: /// kpeter@701: /// The constructor. kpeter@701: /// \param _iim should be given to the constructor, since it is used kpeter@701: /// internally to handle the cross references. The value of the map kpeter@701: /// should be PRE_HEAP (-1) for each element. kpeter@701: explicit KaryHeap(ItemIntMap &_iim, const int &_K=32) : iim(_iim), K(_K) {} kpeter@701: kpeter@701: /// \brief The constructor. kpeter@701: /// kpeter@701: /// The constructor. kpeter@701: /// \param _iim should be given to the constructor, since it is used kpeter@701: /// internally to handle the cross references. The value of the map kpeter@701: /// should be PRE_HEAP (-1) for each element. kpeter@701: /// kpeter@701: /// \param _comp The comparator function object. kpeter@701: KaryHeap(ItemIntMap &_iim, const Compare &_comp, const int &_K=32) kpeter@701: : iim(_iim), comp(_comp), K(_K) {} kpeter@701: kpeter@701: kpeter@701: /// The number of items stored in the heap. kpeter@701: /// kpeter@701: /// \brief Returns the number of items stored in the heap. kpeter@701: int size() const { return data.size(); } kpeter@701: kpeter@701: /// \brief Checks if the heap stores no items. kpeter@701: /// kpeter@701: /// Returns \c true if and only if the heap stores no items. kpeter@701: bool empty() const { return data.empty(); } kpeter@701: kpeter@701: /// \brief Make empty this heap. kpeter@701: /// kpeter@701: /// Make empty this heap. It does not change the cross reference map. kpeter@701: /// If you want to reuse what is not surely empty you should first clear kpeter@701: /// the heap and after that you should set the cross reference map for kpeter@701: /// each item to \c PRE_HEAP. kpeter@701: void clear() { data.clear(); } kpeter@701: kpeter@701: private: kpeter@701: int parent(int i) { return (i-1)/K; } kpeter@701: int first_child(int i) { return K*i+1; } kpeter@701: kpeter@701: bool less(const Pair &p1, const Pair &p2) const { kpeter@701: return comp(p1.second, p2.second); kpeter@701: } kpeter@701: kpeter@701: int find_min(const int child, const int length) { kpeter@701: int min=child, i=1; kpeter@701: while( i0 && less(p,data[par]) ) { kpeter@701: move(data[par],hole); kpeter@701: hole = par; kpeter@701: par = parent(hole); kpeter@701: } kpeter@701: move(p, hole); kpeter@701: } kpeter@701: kpeter@701: void bubble_down(int hole, Pair p, int length) { kpeter@701: if( length>1 ) { kpeter@701: int child = first_child(hole); kpeter@701: while( child0) bubble_down(0, data[n], n); kpeter@701: data.pop_back(); kpeter@701: } kpeter@701: kpeter@701: /// \brief Deletes \c i from the heap. kpeter@701: /// kpeter@701: /// This method deletes item \c i from the heap. kpeter@701: /// \param i The item to erase. kpeter@701: /// \pre The item should be in the heap. kpeter@701: void erase(const Item &i) { kpeter@701: int h = iim[i]; kpeter@701: int n = data.size()-1; kpeter@701: iim.set(data[h].first, POST_HEAP); kpeter@701: if( h=0) s=0; kpeter@701: return State(s); kpeter@701: } kpeter@701: kpeter@701: /// \brief Sets the state of the \c item in the heap. kpeter@701: /// kpeter@701: /// Sets the state of the \c item in the heap. It can be used to kpeter@701: /// manually clear the heap when it is important to achive the kpeter@701: /// better time complexity. kpeter@701: /// \param i The item. kpeter@701: /// \param st The state. It should not be \c IN_HEAP. kpeter@701: void state(const Item& i, State st) { kpeter@701: switch (st) { kpeter@701: case POST_HEAP: kpeter@701: case PRE_HEAP: kpeter@701: if (state(i) == IN_HEAP) erase(i); kpeter@701: iim[i] = st; kpeter@701: break; kpeter@701: case IN_HEAP: kpeter@701: break; kpeter@701: } kpeter@701: } kpeter@701: kpeter@701: /// \brief Replaces an item in the heap. kpeter@701: /// kpeter@701: /// The \c i item is replaced with \c j item. The \c i item should kpeter@701: /// be in the heap, while the \c j should be out of the heap. The kpeter@701: /// \c i item will out of the heap and \c j will be in the heap kpeter@701: /// with the same prioriority as prevoiusly the \c i item. kpeter@701: void replace(const Item& i, const Item& j) { kpeter@701: int idx=iim[i]; kpeter@701: iim.set(i, iim[j]); kpeter@701: iim.set(j, idx); kpeter@701: data[idx].first=j; kpeter@701: } kpeter@701: kpeter@701: }; // class KaryHeap kpeter@701: kpeter@701: } // namespace lemon kpeter@701: kpeter@701: #endif // LEMON_KARY_HEAP_H