lemon/bin_heap.h
changeset 2301 eb378706bd3d
parent 2258 741995f3dbc4
child 2391 14a343be7a5a
equal deleted inserted replaced
9:1e1b4ddaf6b4 10:c5bce0ac200c
    37   ///is a data structure for storing items with specified values called \e
    37   ///is a data structure for storing items with specified values called \e
    38   ///priorities in such a way that finding the item with minimum priority is
    38   ///priorities in such a way that finding the item with minimum priority is
    39   ///efficient. \c Compare specifies the ordering of the priorities. In a heap
    39   ///efficient. \c Compare specifies the ordering of the priorities. In a heap
    40   ///one can change the priority of an item, add or erase an item, etc.
    40   ///one can change the priority of an item, add or erase an item, etc.
    41   ///
    41   ///
    42   ///\param Item Type of the items to be stored.  
       
    43   ///\param Prio Type of the priority of the items.
    42   ///\param Prio Type of the priority of the items.
    44   ///\param ItemIntMap A read and writable Item int map, used internally
    43   ///\param ItemIntMap A read and writable Item int map, used internally
    45   ///to handle the cross references.
    44   ///to handle the cross references.
    46   ///\param Compare A class for the ordering of the priorities. The
    45   ///\param Compare A class for the ordering of the priorities. The
    47   ///default is \c std::less<Prio>.
    46   ///default is \c std::less<Prio>.
    48   ///
    47   ///
    49   ///\sa FibHeap
    48   ///\sa FibHeap
    50   ///\sa Dijkstra
    49   ///\sa Dijkstra
    51   template <typename Item, typename Prio, typename ItemIntMap,
    50   template <typename Prio, typename ItemIntMap,
    52 	    typename Compare = std::less<Prio> >
    51 	    typename Compare = std::less<Prio> >
    53   class BinHeap {
    52   class BinHeap {
    54 
    53 
    55   public:
    54   public:
    56     typedef Item                             ItemType;
    55     typedef typename ItemIntMap::Key         ItemType;
    57     typedef Prio                             PrioType;
    56     typedef Prio                             PrioType;
    58     typedef std::pair<ItemType,PrioType>     PairType;
    57     typedef std::pair<ItemType,PrioType>     PairType;
    59     typedef ItemIntMap                       ItemIntMapType;
    58     typedef ItemIntMap                       ItemIntMapType;
    60     typedef Compare                          PrioCompare;
    59     typedef Compare                          PrioCompare;
    61 
    60 
   159     /// \brief Insert an item into the heap with the given heap.
   158     /// \brief Insert an item into the heap with the given heap.
   160     ///    
   159     ///    
   161     /// Adds \c i to the heap with priority \c p. 
   160     /// Adds \c i to the heap with priority \c p. 
   162     /// \param i The item to insert.
   161     /// \param i The item to insert.
   163     /// \param p The priority of the item.
   162     /// \param p The priority of the item.
   164     void push(const Item &i, const Prio &p) { push(PairType(i,p)); }
   163     void push(const ItemType &i, const Prio &p) { push(PairType(i,p)); }
   165 
   164 
   166     /// \brief Returns the item with minimum priority relative to \c Compare.
   165     /// \brief Returns the item with minimum priority relative to \c Compare.
   167     ///
   166     ///
   168     /// This method returns the item with minimum priority relative to \c
   167     /// This method returns the item with minimum priority relative to \c
   169     /// Compare.  
   168     /// Compare.  
   170     /// \pre The heap must be nonempty.  
   169     /// \pre The heap must be nonempty.  
   171     Item top() const {
   170     ItemType top() const {
   172       return data[0].first;
   171       return data[0].first;
   173     }
   172     }
   174 
   173 
   175     /// \brief Returns the minimum priority relative to \c Compare.
   174     /// \brief Returns the minimum priority relative to \c Compare.
   176     ///
   175     ///
   192     /// \brief Deletes \c i from the heap.
   191     /// \brief Deletes \c i from the heap.
   193     ///
   192     ///
   194     /// This method deletes item \c i from the heap, if \c i was
   193     /// This method deletes item \c i from the heap, if \c i was
   195     /// already stored in the heap.
   194     /// already stored in the heap.
   196     /// \param i The item to erase. 
   195     /// \param i The item to erase. 
   197     void erase(const Item &i) {
   196     void erase(const ItemType &i) {
   198       rmidx(iim[i]);
   197       rmidx(iim[i]);
   199     }
   198     }
   200 
   199 
   201     
   200     
   202     /// \brief Returns the priority of \c i.
   201     /// \brief Returns the priority of \c i.
   203     ///
   202     ///
   204     /// This function returns the priority of item \c i.  
   203     /// This function returns the priority of item \c i.  
   205     /// \pre \c i must be in the heap.
   204     /// \pre \c i must be in the heap.
   206     /// \param i The item.
   205     /// \param i The item.
   207     Prio operator[](const Item &i) const {
   206     Prio operator[](const ItemType &i) const {
   208       int idx = iim[i];
   207       int idx = iim[i];
   209       return data[idx].second;
   208       return data[idx].second;
   210     }
   209     }
   211 
   210 
   212     /// \brief \c i gets to the heap with priority \c p independently 
   211     /// \brief \c i gets to the heap with priority \c p independently 
   214     ///
   213     ///
   215     /// This method calls \ref push(\c i, \c p) if \c i is not stored
   214     /// 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.
   215     /// in the heap and sets the priority of \c i to \c p otherwise.
   217     /// \param i The item.
   216     /// \param i The item.
   218     /// \param p The priority.
   217     /// \param p The priority.
   219     void set(const Item &i, const Prio &p) {
   218     void set(const ItemType &i, const Prio &p) {
   220       int idx = iim[i];
   219       int idx = iim[i];
   221       if( idx < 0 ) {
   220       if( idx < 0 ) {
   222 	push(i,p);
   221 	push(i,p);
   223       }
   222       }
   224       else if( comp(p, data[idx].second) ) {
   223       else if( comp(p, data[idx].second) ) {
   234     /// This method decreases the priority of item \c i to \c p.
   233     /// 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
   234     /// \pre \c i must be stored in the heap with priority at least \c
   236     /// p relative to \c Compare.
   235     /// p relative to \c Compare.
   237     /// \param i The item.
   236     /// \param i The item.
   238     /// \param p The priority.
   237     /// \param p The priority.
   239     void decrease(const Item &i, const Prio &p) {
   238     void decrease(const ItemType &i, const Prio &p) {
   240       int idx = iim[i];
   239       int idx = iim[i];
   241       bubble_up(idx, PairType(i,p));
   240       bubble_up(idx, PairType(i,p));
   242     }
   241     }
   243     
   242     
   244     /// \brief Increases the priority of \c i to \c p.
   243     /// \brief Increases the priority of \c i to \c p.
   246     /// This method sets the priority of item \c i to \c p. 
   245     /// 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
   246     /// \pre \c i must be stored in the heap with priority at most \c
   248     /// p relative to \c Compare.
   247     /// p relative to \c Compare.
   249     /// \param i The item.
   248     /// \param i The item.
   250     /// \param p The priority.
   249     /// \param p The priority.
   251     void increase(const Item &i, const Prio &p) {
   250     void increase(const ItemType &i, const Prio &p) {
   252       int idx = iim[i];
   251       int idx = iim[i];
   253       bubble_down(idx, PairType(i,p), data.size());
   252       bubble_down(idx, PairType(i,p), data.size());
   254     }
   253     }
   255 
   254 
   256     /// \brief Returns if \c item is in, has already been in, or has 
   255     /// \brief Returns if \c item is in, has already been in, or has 
   259     /// This method returns PRE_HEAP if \c item has never been in the
   258     /// 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
   259     /// 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
   260     /// otherwise. In the latter case it is possible that \c item will
   262     /// get back to the heap again.
   261     /// get back to the heap again.
   263     /// \param i The item.
   262     /// \param i The item.
   264     state_enum state(const Item &i) const {
   263     state_enum state(const ItemType &i) const {
   265       int s = iim[i];
   264       int s = iim[i];
   266       if( s>=0 )
   265       if( s>=0 )
   267 	s=0;
   266 	s=0;
   268       return state_enum(s);
   267       return state_enum(s);
   269     }
   268     }
   273     /// Sets the state of the \c item in the heap. It can be used to
   272     /// Sets the state of the \c item in the heap. It can be used to
   274     /// manually clear the heap when it is important to achive the
   273     /// manually clear the heap when it is important to achive the
   275     /// better time complexity.
   274     /// better time complexity.
   276     /// \param i The item.
   275     /// \param i The item.
   277     /// \param st The state. It should not be \c IN_HEAP. 
   276     /// \param st The state. It should not be \c IN_HEAP. 
   278     void state(const Item& i, state_enum st) {
   277     void state(const ItemType& i, state_enum st) {
   279       switch (st) {
   278       switch (st) {
   280       case POST_HEAP:
   279       case POST_HEAP:
   281       case PRE_HEAP:
   280       case PRE_HEAP:
   282         if (state(i) == IN_HEAP) {
   281         if (state(i) == IN_HEAP) {
   283           erase(i);
   282           erase(i);
   290     }
   289     }
   291 
   290 
   292   }; // class BinHeap
   291   }; // class BinHeap
   293 
   292 
   294   
   293   
   295   template <typename K, typename V, typename M, typename C>
   294   template <typename V, typename M, typename C>
   296   int BinHeap<K,V,M,C>::bubble_up(int hole, PairType p) {
   295   int BinHeap<V,M,C>::bubble_up(int hole, PairType p) {
   297     int par = parent(hole);
   296     int par = parent(hole);
   298     while( hole>0 && less(p,data[par]) ) {
   297     while( hole>0 && less(p,data[par]) ) {
   299       move(data[par],hole);
   298       move(data[par],hole);
   300       hole = par;
   299       hole = par;
   301       par = parent(hole);
   300       par = parent(hole);
   302     }
   301     }
   303     move(p, hole);
   302     move(p, hole);
   304     return hole;
   303     return hole;
   305   }
   304   }
   306 
   305 
   307   template <typename K, typename V, typename M, typename C>
   306   template <typename V, typename M, typename C>
   308   int BinHeap<K,V,M,C>::bubble_down(int hole, PairType p, int length) {
   307   int BinHeap<V,M,C>::bubble_down(int hole, PairType p, int length) {
   309     int child = second_child(hole);
   308     int child = second_child(hole);
   310     while(child < length) {
   309     while(child < length) {
   311       if( less(data[child-1], data[child]) ) {
   310       if( less(data[child-1], data[child]) ) {
   312 	--child;
   311 	--child;
   313       }
   312       }