lemon/fib_heap.h
changeset 683 9f529abcaebf
parent 681 532697c9fa53
child 709 0747f332c478
     1.1 --- a/lemon/fib_heap.h	Thu Jun 11 22:16:11 2009 +0200
     1.2 +++ b/lemon/fib_heap.h	Thu Jun 11 23:13:24 2009 +0200
     1.3 @@ -36,87 +36,88 @@
     1.4    ///This class implements the \e Fibonacci \e heap data structure. A \e heap
     1.5    ///is a data structure for storing items with specified values called \e
     1.6    ///priorities in such a way that finding the item with minimum priority is
     1.7 -  ///efficient. \c Compare specifies the ordering of the priorities. In a heap
     1.8 +  ///efficient. \c CMP specifies the ordering of the priorities. In a heap
     1.9    ///one can change the priority of an item, add or erase an item, etc.
    1.10    ///
    1.11    ///The methods \ref increase and \ref erase are not efficient in a Fibonacci
    1.12    ///heap. In case of many calls to these operations, it is better to use a
    1.13    ///\ref BinHeap "binary heap".
    1.14    ///
    1.15 -  ///\param _Prio Type of the priority of the items.
    1.16 -  ///\param _ItemIntMap A read and writable Item int map, used internally
    1.17 +  ///\param PRIO Type of the priority of the items.
    1.18 +  ///\param IM A read and writable Item int map, used internally
    1.19    ///to handle the cross references.
    1.20 -  ///\param _Compare A class for the ordering of the priorities. The
    1.21 -  ///default is \c std::less<_Prio>.
    1.22 +  ///\param CMP A class for the ordering of the priorities. The
    1.23 +  ///default is \c std::less<PRIO>.
    1.24    ///
    1.25    ///\sa BinHeap
    1.26    ///\sa Dijkstra
    1.27  #ifdef DOXYGEN
    1.28 -  template <typename _Prio,
    1.29 -            typename _ItemIntMap,
    1.30 -            typename _Compare>
    1.31 +  template <typename PRIO, typename IM, typename CMP>
    1.32  #else
    1.33 -  template <typename _Prio,
    1.34 -            typename _ItemIntMap,
    1.35 -            typename _Compare = std::less<_Prio> >
    1.36 +  template <typename PRIO, typename IM, typename CMP = std::less<PRIO> >
    1.37  #endif
    1.38    class FibHeap {
    1.39    public:
    1.40      ///\e
    1.41 -    typedef _ItemIntMap ItemIntMap;
    1.42 +    typedef IM ItemIntMap;
    1.43      ///\e
    1.44 -    typedef _Prio Prio;
    1.45 +    typedef PRIO Prio;
    1.46      ///\e
    1.47      typedef typename ItemIntMap::Key Item;
    1.48      ///\e
    1.49      typedef std::pair<Item,Prio> Pair;
    1.50      ///\e
    1.51 -    typedef _Compare Compare;
    1.52 +    typedef CMP Compare;
    1.53  
    1.54    private:
    1.55 -    class store;
    1.56 +    class Store;
    1.57  
    1.58 -    std::vector<store> container;
    1.59 -    int minimum;
    1.60 -    ItemIntMap &iimap;
    1.61 -    Compare comp;
    1.62 -    int num_items;
    1.63 +    std::vector<Store> _data;
    1.64 +    int _minimum;
    1.65 +    ItemIntMap &_iim;
    1.66 +    Compare _comp;
    1.67 +    int _num;
    1.68  
    1.69    public:
    1.70 -    ///Status of the nodes
    1.71 +
    1.72 +    /// \brief Type to represent the items states.
    1.73 +    ///
    1.74 +    /// Each Item element have a state associated to it. It may be "in heap",
    1.75 +    /// "pre heap" or "post heap". The latter two are indifferent from the
    1.76 +    /// heap's point of view, but may be useful to the user.
    1.77 +    ///
    1.78 +    /// The item-int map must be initialized in such way that it assigns
    1.79 +    /// \c PRE_HEAP (<tt>-1</tt>) to any element to be put in the heap.
    1.80      enum State {
    1.81 -      ///The node is in the heap
    1.82 -      IN_HEAP = 0,
    1.83 -      ///The node has never been in the heap
    1.84 -      PRE_HEAP = -1,
    1.85 -      ///The node was in the heap but it got out of it
    1.86 -      POST_HEAP = -2
    1.87 +      IN_HEAP = 0,    ///< = 0.
    1.88 +      PRE_HEAP = -1,  ///< = -1.
    1.89 +      POST_HEAP = -2  ///< = -2.
    1.90      };
    1.91  
    1.92      /// \brief The constructor
    1.93      ///
    1.94 -    /// \c _iimap should be given to the constructor, since it is
    1.95 +    /// \c map should be given to the constructor, since it is
    1.96      ///   used internally to handle the cross references.
    1.97 -    explicit FibHeap(ItemIntMap &_iimap)
    1.98 -      : minimum(0), iimap(_iimap), num_items() {}
    1.99 +    explicit FibHeap(ItemIntMap &map)
   1.100 +      : _minimum(0), _iim(map), _num() {}
   1.101  
   1.102      /// \brief The constructor
   1.103      ///
   1.104 -    /// \c _iimap should be given to the constructor, since it is used
   1.105 -    /// internally to handle the cross references. \c _comp is an
   1.106 +    /// \c map should be given to the constructor, since it is used
   1.107 +    /// internally to handle the cross references. \c comp is an
   1.108      /// object for ordering of the priorities.
   1.109 -    FibHeap(ItemIntMap &_iimap, const Compare &_comp)
   1.110 -      : minimum(0), iimap(_iimap), comp(_comp), num_items() {}
   1.111 +    FibHeap(ItemIntMap &map, const Compare &comp)
   1.112 +      : _minimum(0), _iim(map), _comp(comp), _num() {}
   1.113  
   1.114      /// \brief The number of items stored in the heap.
   1.115      ///
   1.116      /// Returns the number of items stored in the heap.
   1.117 -    int size() const { return num_items; }
   1.118 +    int size() const { return _num; }
   1.119  
   1.120      /// \brief Checks if the heap stores no items.
   1.121      ///
   1.122      ///   Returns \c true if and only if the heap stores no items.
   1.123 -    bool empty() const { return num_items==0; }
   1.124 +    bool empty() const { return _num==0; }
   1.125  
   1.126      /// \brief Make empty this heap.
   1.127      ///
   1.128 @@ -125,7 +126,7 @@
   1.129      /// should first clear the heap and after that you should set the
   1.130      /// cross reference map for each item to \c PRE_HEAP.
   1.131      void clear() {
   1.132 -      container.clear(); minimum = 0; num_items = 0;
   1.133 +      _data.clear(); _minimum = 0; _num = 0;
   1.134      }
   1.135  
   1.136      /// \brief \c item gets to the heap with priority \c value independently
   1.137 @@ -135,10 +136,10 @@
   1.138      /// stored in the heap and it calls \ref decrease(\c item, \c value) or
   1.139      /// \ref increase(\c item, \c value) otherwise.
   1.140      void set (const Item& item, const Prio& value) {
   1.141 -      int i=iimap[item];
   1.142 -      if ( i >= 0 && container[i].in ) {
   1.143 -        if ( comp(value, container[i].prio) ) decrease(item, value);
   1.144 -        if ( comp(container[i].prio, value) ) increase(item, value);
   1.145 +      int i=_iim[item];
   1.146 +      if ( i >= 0 && _data[i].in ) {
   1.147 +        if ( _comp(value, _data[i].prio) ) decrease(item, value);
   1.148 +        if ( _comp(_data[i].prio, value) ) increase(item, value);
   1.149        } else push(item, value);
   1.150      }
   1.151  
   1.152 @@ -147,33 +148,33 @@
   1.153      /// Adds \c item to the heap with priority \c value.
   1.154      /// \pre \c item must not be stored in the heap.
   1.155      void push (const Item& item, const Prio& value) {
   1.156 -      int i=iimap[item];
   1.157 +      int i=_iim[item];
   1.158        if ( i < 0 ) {
   1.159 -        int s=container.size();
   1.160 -        iimap.set( item, s );
   1.161 -        store st;
   1.162 +        int s=_data.size();
   1.163 +        _iim.set( item, s );
   1.164 +        Store st;
   1.165          st.name=item;
   1.166 -        container.push_back(st);
   1.167 +        _data.push_back(st);
   1.168          i=s;
   1.169        } else {
   1.170 -        container[i].parent=container[i].child=-1;
   1.171 -        container[i].degree=0;
   1.172 -        container[i].in=true;
   1.173 -        container[i].marked=false;
   1.174 +        _data[i].parent=_data[i].child=-1;
   1.175 +        _data[i].degree=0;
   1.176 +        _data[i].in=true;
   1.177 +        _data[i].marked=false;
   1.178        }
   1.179  
   1.180 -      if ( num_items ) {
   1.181 -        container[container[minimum].right_neighbor].left_neighbor=i;
   1.182 -        container[i].right_neighbor=container[minimum].right_neighbor;
   1.183 -        container[minimum].right_neighbor=i;
   1.184 -        container[i].left_neighbor=minimum;
   1.185 -        if ( comp( value, container[minimum].prio) ) minimum=i;
   1.186 +      if ( _num ) {
   1.187 +        _data[_data[_minimum].right_neighbor].left_neighbor=i;
   1.188 +        _data[i].right_neighbor=_data[_minimum].right_neighbor;
   1.189 +        _data[_minimum].right_neighbor=i;
   1.190 +        _data[i].left_neighbor=_minimum;
   1.191 +        if ( _comp( value, _data[_minimum].prio) ) _minimum=i;
   1.192        } else {
   1.193 -        container[i].right_neighbor=container[i].left_neighbor=i;
   1.194 -        minimum=i;
   1.195 +        _data[i].right_neighbor=_data[i].left_neighbor=i;
   1.196 +        _minimum=i;
   1.197        }
   1.198 -      container[i].prio=value;
   1.199 -      ++num_items;
   1.200 +      _data[i].prio=value;
   1.201 +      ++_num;
   1.202      }
   1.203  
   1.204      /// \brief Returns the item with minimum priority relative to \c Compare.
   1.205 @@ -181,20 +182,20 @@
   1.206      /// This method returns the item with minimum priority relative to \c
   1.207      /// Compare.
   1.208      /// \pre The heap must be nonempty.
   1.209 -    Item top() const { return container[minimum].name; }
   1.210 +    Item top() const { return _data[_minimum].name; }
   1.211  
   1.212      /// \brief Returns the minimum priority relative to \c Compare.
   1.213      ///
   1.214      /// It returns the minimum priority relative to \c Compare.
   1.215      /// \pre The heap must be nonempty.
   1.216 -    const Prio& prio() const { return container[minimum].prio; }
   1.217 +    const Prio& prio() const { return _data[_minimum].prio; }
   1.218  
   1.219      /// \brief Returns the priority of \c item.
   1.220      ///
   1.221      /// It returns the priority of \c item.
   1.222      /// \pre \c item must be in the heap.
   1.223      const Prio& operator[](const Item& item) const {
   1.224 -      return container[iimap[item]].prio;
   1.225 +      return _data[_iim[item]].prio;
   1.226      }
   1.227  
   1.228      /// \brief Deletes the item with minimum priority relative to \c Compare.
   1.229 @@ -204,33 +205,33 @@
   1.230      /// \pre The heap must be non-empty.
   1.231      void pop() {
   1.232        /*The first case is that there are only one root.*/
   1.233 -      if ( container[minimum].left_neighbor==minimum ) {
   1.234 -        container[minimum].in=false;
   1.235 -        if ( container[minimum].degree!=0 ) {
   1.236 -          makeroot(container[minimum].child);
   1.237 -          minimum=container[minimum].child;
   1.238 +      if ( _data[_minimum].left_neighbor==_minimum ) {
   1.239 +        _data[_minimum].in=false;
   1.240 +        if ( _data[_minimum].degree!=0 ) {
   1.241 +          makeroot(_data[_minimum].child);
   1.242 +          _minimum=_data[_minimum].child;
   1.243            balance();
   1.244          }
   1.245        } else {
   1.246 -        int right=container[minimum].right_neighbor;
   1.247 -        unlace(minimum);
   1.248 -        container[minimum].in=false;
   1.249 -        if ( container[minimum].degree > 0 ) {
   1.250 -          int left=container[minimum].left_neighbor;
   1.251 -          int child=container[minimum].child;
   1.252 -          int last_child=container[child].left_neighbor;
   1.253 +        int right=_data[_minimum].right_neighbor;
   1.254 +        unlace(_minimum);
   1.255 +        _data[_minimum].in=false;
   1.256 +        if ( _data[_minimum].degree > 0 ) {
   1.257 +          int left=_data[_minimum].left_neighbor;
   1.258 +          int child=_data[_minimum].child;
   1.259 +          int last_child=_data[child].left_neighbor;
   1.260  
   1.261            makeroot(child);
   1.262  
   1.263 -          container[left].right_neighbor=child;
   1.264 -          container[child].left_neighbor=left;
   1.265 -          container[right].left_neighbor=last_child;
   1.266 -          container[last_child].right_neighbor=right;
   1.267 +          _data[left].right_neighbor=child;
   1.268 +          _data[child].left_neighbor=left;
   1.269 +          _data[right].left_neighbor=last_child;
   1.270 +          _data[last_child].right_neighbor=right;
   1.271          }
   1.272 -        minimum=right;
   1.273 +        _minimum=right;
   1.274          balance();
   1.275        } // the case where there are more roots
   1.276 -      --num_items;
   1.277 +      --_num;
   1.278      }
   1.279  
   1.280      /// \brief Deletes \c item from the heap.
   1.281 @@ -238,15 +239,15 @@
   1.282      /// This method deletes \c item from the heap, if \c item was already
   1.283      /// stored in the heap. It is quite inefficient in Fibonacci heaps.
   1.284      void erase (const Item& item) {
   1.285 -      int i=iimap[item];
   1.286 +      int i=_iim[item];
   1.287  
   1.288 -      if ( i >= 0 && container[i].in ) {
   1.289 -        if ( container[i].parent!=-1 ) {
   1.290 -          int p=container[i].parent;
   1.291 +      if ( i >= 0 && _data[i].in ) {
   1.292 +        if ( _data[i].parent!=-1 ) {
   1.293 +          int p=_data[i].parent;
   1.294            cut(i,p);
   1.295            cascade(p);
   1.296          }
   1.297 -        minimum=i;     //As if its prio would be -infinity
   1.298 +        _minimum=i;     //As if its prio would be -infinity
   1.299          pop();
   1.300        }
   1.301      }
   1.302 @@ -257,15 +258,15 @@
   1.303      /// \pre \c item must be stored in the heap with priority at least \c
   1.304      ///   value relative to \c Compare.
   1.305      void decrease (Item item, const Prio& value) {
   1.306 -      int i=iimap[item];
   1.307 -      container[i].prio=value;
   1.308 -      int p=container[i].parent;
   1.309 +      int i=_iim[item];
   1.310 +      _data[i].prio=value;
   1.311 +      int p=_data[i].parent;
   1.312  
   1.313 -      if ( p!=-1 && comp(value, container[p].prio) ) {
   1.314 +      if ( p!=-1 && _comp(value, _data[p].prio) ) {
   1.315          cut(i,p);
   1.316          cascade(p);
   1.317        }
   1.318 -      if ( comp(value, container[minimum].prio) ) minimum=i;
   1.319 +      if ( _comp(value, _data[_minimum].prio) ) _minimum=i;
   1.320      }
   1.321  
   1.322      /// \brief Increases the priority of \c item to \c value.
   1.323 @@ -289,9 +290,9 @@
   1.324      /// otherwise. In the latter case it is possible that \c item will
   1.325      /// get back to the heap again.
   1.326      State state(const Item &item) const {
   1.327 -      int i=iimap[item];
   1.328 +      int i=_iim[item];
   1.329        if( i>=0 ) {
   1.330 -        if ( container[i].in ) i=0;
   1.331 +        if ( _data[i].in ) i=0;
   1.332          else i=-2;
   1.333        }
   1.334        return State(i);
   1.335 @@ -301,7 +302,7 @@
   1.336      ///
   1.337      /// Sets the state of the \c item in the heap. It can be used to
   1.338      /// manually clear the heap when it is important to achive the
   1.339 -    /// better time complexity.
   1.340 +    /// better time _complexity.
   1.341      /// \param i The item.
   1.342      /// \param st The state. It should not be \c IN_HEAP.
   1.343      void state(const Item& i, State st) {
   1.344 @@ -311,7 +312,7 @@
   1.345          if (state(i) == IN_HEAP) {
   1.346            erase(i);
   1.347          }
   1.348 -        iimap[i] = st;
   1.349 +        _iim[i] = st;
   1.350          break;
   1.351        case IN_HEAP:
   1.352          break;
   1.353 @@ -322,7 +323,7 @@
   1.354  
   1.355      void balance() {
   1.356  
   1.357 -      int maxdeg=int( std::floor( 2.08*log(double(container.size()))))+1;
   1.358 +      int maxdeg=int( std::floor( 2.08*log(double(_data.size()))))+1;
   1.359  
   1.360        std::vector<int> A(maxdeg,-1);
   1.361  
   1.362 @@ -330,18 +331,18 @@
   1.363         *Recall that now minimum does not point to the minimum prio element.
   1.364         *We set minimum to this during balance().
   1.365         */
   1.366 -      int anchor=container[minimum].left_neighbor;
   1.367 -      int next=minimum;
   1.368 +      int anchor=_data[_minimum].left_neighbor;
   1.369 +      int next=_minimum;
   1.370        bool end=false;
   1.371  
   1.372        do {
   1.373          int active=next;
   1.374          if ( anchor==active ) end=true;
   1.375 -        int d=container[active].degree;
   1.376 -        next=container[active].right_neighbor;
   1.377 +        int d=_data[active].degree;
   1.378 +        next=_data[active].right_neighbor;
   1.379  
   1.380          while (A[d]!=-1) {
   1.381 -          if( comp(container[active].prio, container[A[d]].prio) ) {
   1.382 +          if( _comp(_data[active].prio, _data[A[d]].prio) ) {
   1.383              fuse(active,A[d]);
   1.384            } else {
   1.385              fuse(A[d],active);
   1.386 @@ -354,21 +355,21 @@
   1.387        } while ( !end );
   1.388  
   1.389  
   1.390 -      while ( container[minimum].parent >=0 )
   1.391 -        minimum=container[minimum].parent;
   1.392 -      int s=minimum;
   1.393 -      int m=minimum;
   1.394 +      while ( _data[_minimum].parent >=0 )
   1.395 +        _minimum=_data[_minimum].parent;
   1.396 +      int s=_minimum;
   1.397 +      int m=_minimum;
   1.398        do {
   1.399 -        if ( comp(container[s].prio, container[minimum].prio) ) minimum=s;
   1.400 -        s=container[s].right_neighbor;
   1.401 +        if ( _comp(_data[s].prio, _data[_minimum].prio) ) _minimum=s;
   1.402 +        s=_data[s].right_neighbor;
   1.403        } while ( s != m );
   1.404      }
   1.405  
   1.406      void makeroot(int c) {
   1.407        int s=c;
   1.408        do {
   1.409 -        container[s].parent=-1;
   1.410 -        s=container[s].right_neighbor;
   1.411 +        _data[s].parent=-1;
   1.412 +        s=_data[s].right_neighbor;
   1.413        } while ( s != c );
   1.414      }
   1.415  
   1.416 @@ -376,32 +377,32 @@
   1.417        /*
   1.418         *Replacing a from the children of b.
   1.419         */
   1.420 -      --container[b].degree;
   1.421 +      --_data[b].degree;
   1.422  
   1.423 -      if ( container[b].degree !=0 ) {
   1.424 -        int child=container[b].child;
   1.425 +      if ( _data[b].degree !=0 ) {
   1.426 +        int child=_data[b].child;
   1.427          if ( child==a )
   1.428 -          container[b].child=container[child].right_neighbor;
   1.429 +          _data[b].child=_data[child].right_neighbor;
   1.430          unlace(a);
   1.431        }
   1.432  
   1.433  
   1.434        /*Lacing a to the roots.*/
   1.435 -      int right=container[minimum].right_neighbor;
   1.436 -      container[minimum].right_neighbor=a;
   1.437 -      container[a].left_neighbor=minimum;
   1.438 -      container[a].right_neighbor=right;
   1.439 -      container[right].left_neighbor=a;
   1.440 +      int right=_data[_minimum].right_neighbor;
   1.441 +      _data[_minimum].right_neighbor=a;
   1.442 +      _data[a].left_neighbor=_minimum;
   1.443 +      _data[a].right_neighbor=right;
   1.444 +      _data[right].left_neighbor=a;
   1.445  
   1.446 -      container[a].parent=-1;
   1.447 -      container[a].marked=false;
   1.448 +      _data[a].parent=-1;
   1.449 +      _data[a].marked=false;
   1.450      }
   1.451  
   1.452      void cascade(int a) {
   1.453 -      if ( container[a].parent!=-1 ) {
   1.454 -        int p=container[a].parent;
   1.455 +      if ( _data[a].parent!=-1 ) {
   1.456 +        int p=_data[a].parent;
   1.457  
   1.458 -        if ( container[a].marked==false ) container[a].marked=true;
   1.459 +        if ( _data[a].marked==false ) _data[a].marked=true;
   1.460          else {
   1.461            cut(a,p);
   1.462            cascade(p);
   1.463 @@ -413,38 +414,38 @@
   1.464        unlace(b);
   1.465  
   1.466        /*Lacing b under a.*/
   1.467 -      container[b].parent=a;
   1.468 +      _data[b].parent=a;
   1.469  
   1.470 -      if (container[a].degree==0) {
   1.471 -        container[b].left_neighbor=b;
   1.472 -        container[b].right_neighbor=b;
   1.473 -        container[a].child=b;
   1.474 +      if (_data[a].degree==0) {
   1.475 +        _data[b].left_neighbor=b;
   1.476 +        _data[b].right_neighbor=b;
   1.477 +        _data[a].child=b;
   1.478        } else {
   1.479 -        int child=container[a].child;
   1.480 -        int last_child=container[child].left_neighbor;
   1.481 -        container[child].left_neighbor=b;
   1.482 -        container[b].right_neighbor=child;
   1.483 -        container[last_child].right_neighbor=b;
   1.484 -        container[b].left_neighbor=last_child;
   1.485 +        int child=_data[a].child;
   1.486 +        int last_child=_data[child].left_neighbor;
   1.487 +        _data[child].left_neighbor=b;
   1.488 +        _data[b].right_neighbor=child;
   1.489 +        _data[last_child].right_neighbor=b;
   1.490 +        _data[b].left_neighbor=last_child;
   1.491        }
   1.492  
   1.493 -      ++container[a].degree;
   1.494 +      ++_data[a].degree;
   1.495  
   1.496 -      container[b].marked=false;
   1.497 +      _data[b].marked=false;
   1.498      }
   1.499  
   1.500      /*
   1.501       *It is invoked only if a has siblings.
   1.502       */
   1.503      void unlace(int a) {
   1.504 -      int leftn=container[a].left_neighbor;
   1.505 -      int rightn=container[a].right_neighbor;
   1.506 -      container[leftn].right_neighbor=rightn;
   1.507 -      container[rightn].left_neighbor=leftn;
   1.508 +      int leftn=_data[a].left_neighbor;
   1.509 +      int rightn=_data[a].right_neighbor;
   1.510 +      _data[leftn].right_neighbor=rightn;
   1.511 +      _data[rightn].left_neighbor=leftn;
   1.512      }
   1.513  
   1.514  
   1.515 -    class store {
   1.516 +    class Store {
   1.517        friend class FibHeap;
   1.518  
   1.519        Item name;
   1.520 @@ -457,7 +458,7 @@
   1.521        bool in;
   1.522        Prio prio;
   1.523  
   1.524 -      store() : parent(-1), child(-1), degree(), marked(false), in(true) {}
   1.525 +      Store() : parent(-1), child(-1), degree(), marked(false), in(true) {}
   1.526      };
   1.527    };
   1.528