lemon/bin_heap.h
author hegyi
Mon, 21 Nov 2005 18:03:20 +0000
changeset 1823 cb082cdf3667
parent 1435 8e85e6bbefdf
child 1834 0a14e1ae45a1
permissions -rw-r--r--
NewMapWin has become Dialog instead of Window. Therefore it is created dynamically, when there is need for it, instead of keeping one instance in memory. This solution is slower, but more correct than before.
     1 /* -*- C++ -*-
     2  * lemon/bin_heap.h - Part of LEMON, a generic C++ optimization library
     3  *
     4  * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     5  * (Egervary Research Group on Combinatorial Optimization, EGRES).
     6  *
     7  * Permission to use, modify and distribute this software is granted
     8  * provided that this copyright notice appears in all copies. For
     9  * precise terms see the accompanying LICENSE file.
    10  *
    11  * This software is provided "AS IS" with no warranty of any kind,
    12  * express or implied, and with no claim as to its suitability for any
    13  * purpose.
    14  *
    15  */
    16 
    17 #ifndef LEMON_BIN_HEAP_H
    18 #define LEMON_BIN_HEAP_H
    19 
    20 ///\ingroup auxdat
    21 ///\file
    22 ///\brief Binary Heap implementation.
    23 
    24 #include <vector>
    25 #include <utility>
    26 #include <functional>
    27 
    28 namespace lemon {
    29 
    30   /// \addtogroup auxdat
    31   /// @{
    32 
    33   /// A Binary Heap implementation.
    34   
    35   ///This class implements the \e binary \e heap data structure. A \e heap
    36   ///is a data structure for storing items with specified values called \e
    37   ///priorities in such a way that finding the item with minimum priority is
    38   ///efficient. \c Compare specifies the ordering of the priorities. In a heap
    39   ///one can change the priority of an item, add or erase an item, etc.
    40   ///
    41   ///\param Item Type of the items to be stored.  
    42   ///\param Prio Type of the priority of the items.
    43   ///\param ItemIntMap A read and writable Item int map, used internally
    44   ///to handle the cross references.
    45   ///\param Compare A class for the ordering of the priorities. The
    46   ///default is \c std::less<Prio>.
    47   ///
    48   ///\sa FibHeap
    49   ///\sa Dijkstra
    50   template <typename Item, typename Prio, typename ItemIntMap,
    51 	    typename Compare = std::less<Prio> >
    52   class BinHeap {
    53 
    54   public:
    55     typedef Item                             ItemType;
    56     // FIXME: stl-ben nem ezt hivjak value_type -nak, hanem a kovetkezot...
    57     typedef Prio                             PrioType;
    58     typedef std::pair<ItemType,PrioType>     PairType;
    59     typedef ItemIntMap                       ItemIntMapType;
    60     typedef Compare                          PrioCompare;
    61 
    62     /// \brief Type to represent the items states.
    63     ///
    64     /// Each Item element have a state associated to it. It may be "in heap",
    65     /// "pre heap" or "post heap". The latter two are indifferent from the
    66     /// heap's point of view, but may be useful to the user.
    67     ///
    68     /// The ItemIntMap \e should be initialized in such way that it maps
    69     /// PRE_HEAP (-1) to any element to be put in the heap...
    70     enum state_enum {
    71       IN_HEAP = 0,
    72       PRE_HEAP = -1,
    73       POST_HEAP = -2
    74     };
    75 
    76   private:
    77     std::vector<PairType> data;
    78     Compare comp;
    79     ItemIntMap &iim;
    80 
    81   public:
    82     /// \brief The constructor.
    83     ///
    84     /// The constructor.
    85     /// \param _iim should be given to the constructor, since it is used
    86     /// internally to handle the cross references. The value of the map
    87     /// should be PRE_HEAP (-1) for each element.
    88     explicit BinHeap(ItemIntMap &_iim) : iim(_iim) {}
    89     
    90     /// \brief The constructor.
    91     ///
    92     /// The constructor.
    93     /// \param _iim should be given to the constructor, since it is used
    94     /// internally to handle the cross references. The value of the map
    95     /// should be PRE_HEAP (-1) for each element.
    96     ///
    97     /// \param _comp The comparator function object.
    98     BinHeap(ItemIntMap &_iim, const Compare &_comp) 
    99       : iim(_iim), comp(_comp) {}
   100 
   101 
   102     /// The number of items stored in the heap.
   103     ///
   104     /// \brief Returns the number of items stored in the heap.
   105     int size() const { return data.size(); }
   106     
   107     /// \brief Checks if the heap stores no items.
   108     ///
   109     /// Returns \c true if and only if the heap stores no items.
   110     bool empty() const { return data.empty(); }
   111 
   112     /// \brief Make empty this heap.
   113     /// 
   114     /// Make empty this heap.
   115     void clear() { 
   116       for (int i = 0; i < (int)data.size(); ++i) {
   117 	iim.set(data[i].first, POST_HEAP);
   118       }
   119       data.clear(); 
   120     }
   121 
   122   private:
   123     static int parent(int i) { return (i-1)/2; }
   124     static int second_child(int i) { return 2*i+2; }
   125     bool less(const PairType &p1, const PairType &p2) const {
   126       return comp(p1.second, p2.second);
   127     }
   128 
   129     int bubble_up(int hole, PairType p);
   130     int bubble_down(int hole, PairType p, int length);
   131 
   132     void move(const PairType &p, int i) {
   133       data[i] = p;
   134       iim.set(p.first, i);
   135     }
   136 
   137     void rmidx(int h) {
   138       int n = data.size()-1;
   139       if( h>=0 && h<=n ) {
   140 	iim.set(data[h].first, POST_HEAP);
   141 	if ( h<n ) {
   142 	  bubble_down(h, data[n], n);
   143 	}
   144 	data.pop_back();
   145       }
   146     }
   147 
   148   public:
   149     /// \brief Insert a pair of item and priority into the heap.
   150     ///
   151     /// Adds \c p.first to the heap with priority \c p.second.
   152     /// \param p The pair to insert.
   153     void push(const PairType &p) {
   154       int n = data.size();
   155       data.resize(n+1);
   156       bubble_up(n, p);
   157     }
   158 
   159     /// \brief Insert an item into the heap with the given heap.
   160     ///    
   161     /// Adds \c i to the heap with priority \c p. 
   162     /// \param i The item to insert.
   163     /// \param p The priority of the item.
   164     void push(const Item &i, const Prio &p) { push(PairType(i,p)); }
   165 
   166     /// \brief Returns the item with minimum priority relative to \c Compare.
   167     ///
   168     /// This method returns the item with minimum priority relative to \c
   169     /// Compare.  
   170     /// \pre The heap must be nonempty.  
   171     Item top() const {
   172       return data[0].first;
   173     }
   174 
   175     /// \brief Returns the minimum priority relative to \c Compare.
   176     ///
   177     /// It returns the minimum priority relative to \c Compare.
   178     /// \pre The heap must be nonempty.
   179     Prio prio() const {
   180       return data[0].second;
   181     }
   182 
   183     /// \brief Deletes the item with minimum priority relative to \c Compare.
   184     ///
   185     /// This method deletes the item with minimum priority relative to \c
   186     /// Compare from the heap.  
   187     /// \pre The heap must be non-empty.  
   188     void pop() {
   189       rmidx(0);
   190     }
   191 
   192     /// \brief Deletes \c i from the heap.
   193     ///
   194     /// This method deletes item \c i from the heap, if \c i was
   195     /// already stored in the heap.
   196     /// \param i The item to erase. 
   197     void erase(const Item &i) {
   198       rmidx(iim[i]);
   199     }
   200 
   201     
   202     /// \brief Returns the priority of \c i.
   203     ///
   204     /// This function returns the priority of item \c i.  
   205     /// \pre \c i must be in the heap.
   206     /// \param i The item.
   207     Prio operator[](const Item &i) const {
   208       int idx = iim[i];
   209       return data[idx].second;
   210     }
   211 
   212     /// \brief \c i gets to the heap with priority \c p independently 
   213     /// if \c i was already there.
   214     ///
   215     /// This method calls \ref push(\c i, \c p) if \c i is not stored
   216     /// in the heap and sets the priority of \c i to \c p otherwise.
   217     /// \param i The item.
   218     /// \param p The priority.
   219     void set(const Item &i, const Prio &p) {
   220       int idx = iim[i];
   221       if( idx < 0 ) {
   222 	push(i,p);
   223       }
   224       else if( comp(p, data[idx].second) ) {
   225 	bubble_up(idx, PairType(i,p));
   226       }
   227       else {
   228 	bubble_down(idx, PairType(i,p), data.size());
   229       }
   230     }
   231 
   232     /// \brief Decreases the priority of \c i to \c p.
   233 
   234     /// This method decreases the priority of item \c i to \c p.
   235     /// \pre \c i must be stored in the heap with priority at least \c
   236     /// p relative to \c Compare.
   237     /// \param i The item.
   238     /// \param p The priority.
   239     void decrease(const Item &i, const Prio &p) {
   240       int idx = iim[i];
   241       bubble_up(idx, PairType(i,p));
   242     }
   243     
   244     /// \brief Increases the priority of \c i to \c p.
   245     ///
   246     /// This method sets the priority of item \c i to \c p. 
   247     /// \pre \c i must be stored in the heap with priority at most \c
   248     /// p relative to \c Compare.
   249     /// \param i The item.
   250     /// \param p The priority.
   251     void increase(const Item &i, const Prio &p) {
   252       int idx = iim[i];
   253       bubble_down(idx, PairType(i,p), data.size());
   254     }
   255 
   256     /// \brief Returns if \c item is in, has already been in, or has 
   257     /// never been in the heap.
   258     ///
   259     /// This method returns PRE_HEAP if \c item has never been in the
   260     /// heap, IN_HEAP if it is in the heap at the moment, and POST_HEAP
   261     /// otherwise. In the latter case it is possible that \c item will
   262     /// get back to the heap again.
   263     /// \param i The item.
   264     state_enum state(const Item &i) const {
   265       int s = iim[i];
   266       if( s>=0 )
   267 	s=0;
   268       return state_enum(s);
   269     }
   270 
   271   }; // class BinHeap
   272 
   273   
   274   template <typename K, typename V, typename M, typename C>
   275   int BinHeap<K,V,M,C>::bubble_up(int hole, PairType p) {
   276     int par = parent(hole);
   277     while( hole>0 && less(p,data[par]) ) {
   278       move(data[par],hole);
   279       hole = par;
   280       par = parent(hole);
   281     }
   282     move(p, hole);
   283     return hole;
   284   }
   285 
   286   template <typename K, typename V, typename M, typename C>
   287   int BinHeap<K,V,M,C>::bubble_down(int hole, PairType p, int length) {
   288     int child = second_child(hole);
   289     while(child < length) {
   290       if( less(data[child-1], data[child]) ) {
   291 	--child;
   292       }
   293       if( !less(data[child], p) )
   294 	goto ok;
   295       move(data[child], hole);
   296       hole = child;
   297       child = second_child(hole);
   298     }
   299     child--;
   300     if( child<length && less(data[child], p) ) {
   301       move(data[child], hole);
   302       hole=child;
   303     }
   304   ok:
   305     move(p, hole);
   306     return hole;
   307   }
   308 
   309   ///@}
   310 
   311 } // namespace lemon
   312 
   313 #endif // LEMON_BIN_HEAP_H