gravatar
kpeter (Peter Kovacs)
kpeter@inf.elte.hu
Improve and unify the doc + names in the new heaps (#301)
0 4 0
default
4 files changed with 839 insertions and 820 deletions:
↑ Collapse diff ↑
Ignore white space 6 line context
1
/* -*- C++ -*-
1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 2
 *
3
 * This file is a part of LEMON, a generic C++ optimization library
3
 * This file is a part of LEMON, a generic C++ optimization library.
4 4
 *
5
 * Copyright (C) 2003-2008
5
 * Copyright (C) 2003-2009
6 6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 8
 *
9 9
 * Permission to use, modify and distribute this software is granted
10 10
 * provided that this copyright notice appears in all copies. For
11 11
 * precise terms see the accompanying LICENSE file.
12 12
 *
13 13
 * This software is provided "AS IS" with no warranty of any kind,
14 14
 * express or implied, and with no claim as to its suitability for any
15 15
 * purpose.
16 16
 *
17 17
 */
18 18

	
19 19
#ifndef LEMON_BINOM_HEAP_H
20 20
#define LEMON_BINOM_HEAP_H
21 21

	
22 22
///\file
23
///\ingroup auxdat
23
///\ingroup heaps
24 24
///\brief Binomial Heap implementation.
25 25

	
26 26
#include <vector>
27
#include <utility>
27 28
#include <functional>
28 29
#include <lemon/math.h>
29 30
#include <lemon/counter.h>
30 31

	
31 32
namespace lemon {
32 33

	
33
  /// \ingroup auxdat
34
  /// \ingroup heaps
34 35
  ///
35
  ///\brief Binomial Heap.
36
  ///\brief Binomial heap data structure.
36 37
  ///
37
  ///This class implements the \e Binomial \e heap data structure. A \e heap
38
  ///is a data structure for storing items with specified values called \e
39
  ///priorities in such a way that finding the item with minimum priority is
40
  ///efficient. \c Compare specifies the ordering of the priorities. In a heap
41
  ///one can change the priority of an item, add or erase an item, etc.
38
  /// This class implements the \e binomial \e heap data structure.
39
  /// It fully conforms to the \ref concepts::Heap "heap concept".
42 40
  ///
43
  ///The methods \ref increase and \ref erase are not efficient in a Binomial
44
  ///heap. In case of many calls to these operations, it is better to use a
45
  ///\ref BinHeap "binary heap".
41
  /// The methods \ref increase() and \ref erase() are not efficient
42
  /// in a binomial heap. In case of many calls of these operations,
43
  /// it is better to use other heap structure, e.g. \ref BinHeap
44
  /// "binary heap".
46 45
  ///
47
  ///\param _Prio Type of the priority of the items.
48
  ///\param _ItemIntMap A read and writable Item int map, used internally
49
  ///to handle the cross references.
50
  ///\param _Compare A class for the ordering of the priorities. The
51
  ///default is \c std::less<_Prio>.
52
  ///
53
  ///\sa BinHeap
54
  ///\sa Dijkstra
55
  ///\author Dorian Batha
56

	
46
  /// \tparam PR Type of the priorities of the items.
47
  /// \tparam IM A read-writable item map with \c int values, used
48
  /// internally to handle the cross references.
49
  /// \tparam CMP A functor class for comparing the priorities.
50
  /// The default is \c std::less<PR>.
57 51
#ifdef DOXYGEN
58
  template <typename _Prio,
59
            typename _ItemIntMap,
60
            typename _Compare>
52
  template <typename PR, typename IM, typename CMP>
61 53
#else
62
  template <typename _Prio,
63
            typename _ItemIntMap,
64
            typename _Compare = std::less<_Prio> >
54
  template <typename PR, typename IM, typename CMP = std::less<PR> >
65 55
#endif
66 56
  class BinomHeap {
67 57
  public:
68
    typedef _ItemIntMap ItemIntMap;
69
    typedef _Prio Prio;
58
    /// Type of the item-int map.
59
    typedef IM ItemIntMap;
60
    /// Type of the priorities.
61
    typedef PR Prio;
62
    /// Type of the items stored in the heap.
70 63
    typedef typename ItemIntMap::Key Item;
71
    typedef std::pair<Item,Prio> Pair;
72
    typedef _Compare Compare;
64
    /// Functor type for comparing the priorities.
65
    typedef CMP Compare;
66

	
67
    /// \brief Type to represent the states of the items.
68
    ///
69
    /// Each item has a state associated to it. It can be "in heap",
70
    /// "pre-heap" or "post-heap". The latter two are indifferent from the
71
    /// heap's point of view, but may be useful to the user.
72
    ///
73
    /// The item-int map must be initialized in such way that it assigns
74
    /// \c PRE_HEAP (<tt>-1</tt>) to any element to be put in the heap.
75
    enum State {
76
      IN_HEAP = 0,    ///< = 0.
77
      PRE_HEAP = -1,  ///< = -1.
78
      POST_HEAP = -2  ///< = -2.
79
    };
73 80

	
74 81
  private:
75 82
    class store;
76 83

	
77
    std::vector<store> container;
78
    int minimum, head;
79
    ItemIntMap &iimap;
80
    Compare comp;
81
    int num_items;
84
    std::vector<store> _data;
85
    int _min, _head;
86
    ItemIntMap &_iim;
87
    Compare _comp;
88
    int _num_items;
82 89

	
83 90
  public:
84
    ///Status of the nodes
85
    enum State {
86
      ///The node is in the heap
87
      IN_HEAP = 0,
88
      ///The node has never been in the heap
89
      PRE_HEAP = -1,
90
      ///The node was in the heap but it got out of it
91
      POST_HEAP = -2
92
    };
91
    /// \brief Constructor.
92
    ///
93
    /// Constructor.
94
    /// \param map A map that assigns \c int values to the items.
95
    /// It is used internally to handle the cross references.
96
    /// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
97
    explicit BinomHeap(ItemIntMap &map)
98
      : _min(0), _head(-1), _iim(map), _num_items(0) {}
93 99

	
94
    /// \brief The constructor
100
    /// \brief Constructor.
95 101
    ///
96
    /// \c _iimap should be given to the constructor, since it is
97
    ///   used internally to handle the cross references.
98
    explicit BinomHeap(ItemIntMap &_iimap)
99
      : minimum(0), head(-1), iimap(_iimap), num_items() {}
100

	
101
    /// \brief The constructor
102
    ///
103
    /// \c _iimap should be given to the constructor, since it is used
104
    /// internally to handle the cross references. \c _comp is an
105
    /// object for ordering of the priorities.
106
    BinomHeap(ItemIntMap &_iimap, const Compare &_comp)
107
      : minimum(0), head(-1), iimap(_iimap), comp(_comp), num_items() {}
102
    /// Constructor.
103
    /// \param map A map that assigns \c int values to the items.
104
    /// It is used internally to handle the cross references.
105
    /// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
106
    /// \param comp The function object used for comparing the priorities.
107
    BinomHeap(ItemIntMap &map, const Compare &comp)
108
      : _min(0), _head(-1), _iim(map), _comp(comp), _num_items(0) {}
108 109

	
109 110
    /// \brief The number of items stored in the heap.
110 111
    ///
111
    /// Returns the number of items stored in the heap.
112
    int size() const { return num_items; }
112
    /// This function returns the number of items stored in the heap.
113
    int size() const { return _num_items; }
113 114

	
114
    /// \brief Checks if the heap stores no items.
115
    /// \brief Check if the heap is empty.
115 116
    ///
116
    ///   Returns \c true if and only if the heap stores no items.
117
    bool empty() const { return num_items==0; }
117
    /// This function returns \c true if the heap is empty.
118
    bool empty() const { return _num_items==0; }
118 119

	
119
    /// \brief Make empty this heap.
120
    /// \brief Make the heap empty.
120 121
    ///
121
    /// Make empty this heap. It does not change the cross reference
122
    /// map.  If you want to reuse a heap what is not surely empty you
123
    /// should first clear the heap and after that you should set the
124
    /// cross reference map for each item to \c PRE_HEAP.
122
    /// This functon makes the heap empty.
123
    /// It does not change the cross reference map. If you want to reuse
124
    /// a heap that is not surely empty, you should first clear it and
125
    /// then you should set the cross reference map to \c PRE_HEAP
126
    /// for each item.
125 127
    void clear() {
126
      container.clear(); minimum=0; num_items=0; head=-1;
128
      _data.clear(); _min=0; _num_items=0; _head=-1;
127 129
    }
128 130

	
129
    /// \brief \c item gets to the heap with priority \c value independently
130
    /// if \c item was already there.
131
    /// \brief Set the priority of an item or insert it, if it is
132
    /// not stored in the heap.
131 133
    ///
132
    /// This method calls \ref push(\c item, \c value) if \c item is not
133
    /// stored in the heap and it calls \ref decrease(\c item, \c value) or
134
    /// \ref increase(\c item, \c value) otherwise.
134
    /// This method sets the priority of the given item if it is
135
    /// already stored in the heap. Otherwise it inserts the given
136
    /// item into the heap with the given priority.
137
    /// \param item The item.
138
    /// \param value The priority.
135 139
    void set (const Item& item, const Prio& value) {
136
      int i=iimap[item];
137
      if ( i >= 0 && container[i].in ) {
138
        if ( comp(value, container[i].prio) ) decrease(item, value);
139
        if ( comp(container[i].prio, value) ) increase(item, value);
140
      int i=_iim[item];
141
      if ( i >= 0 && _data[i].in ) {
142
        if ( _comp(value, _data[i].prio) ) decrease(item, value);
143
        if ( _comp(_data[i].prio, value) ) increase(item, value);
140 144
      } else push(item, value);
141 145
    }
142 146

	
143
    /// \brief Adds \c item to the heap with priority \c value.
147
    /// \brief Insert an item into the heap with the given priority.
144 148
    ///
145
    /// Adds \c item to the heap with priority \c value.
146
    /// \pre \c item must not be stored in the heap.
149
    /// This function inserts the given item into the heap with the
150
    /// given priority.
151
    /// \param item The item to insert.
152
    /// \param value The priority of the item.
153
    /// \pre \e item must not be stored in the heap.
147 154
    void push (const Item& item, const Prio& value) {
148
      int i=iimap[item];
155
      int i=_iim[item];
149 156
      if ( i<0 ) {
150
        int s=container.size();
151
        iimap.set( item,s );
157
        int s=_data.size();
158
        _iim.set( item,s );
152 159
        store st;
153 160
        st.name=item;
154
        container.push_back(st);
161
        _data.push_back(st);
155 162
        i=s;
156 163
      }
157 164
      else {
158
        container[i].parent=container[i].right_neighbor=container[i].child=-1;
159
        container[i].degree=0;
160
        container[i].in=true;
165
        _data[i].parent=_data[i].right_neighbor=_data[i].child=-1;
166
        _data[i].degree=0;
167
        _data[i].in=true;
161 168
      }
162
      container[i].prio=value;
169
      _data[i].prio=value;
163 170

	
164
      if( 0==num_items ) { head=i; minimum=i; }
171
      if( 0==_num_items ) { _head=i; _min=i; }
165 172
      else { merge(i); }
166 173

	
167
      minimum = find_min();
174
      _min = findMin();
168 175

	
169
      ++num_items;
176
      ++_num_items;
170 177
    }
171 178

	
172
    /// \brief Returns the item with minimum priority relative to \c Compare.
179
    /// \brief Return the item having minimum priority.
173 180
    ///
174
    /// This method returns the item with minimum priority relative to \c
175
    /// Compare.
176
    /// \pre The heap must be nonempty.
177
    Item top() const { return container[minimum].name; }
181
    /// This function returns the item having minimum priority.
182
    /// \pre The heap must be non-empty.
183
    Item top() const { return _data[_min].name; }
178 184

	
179
    /// \brief Returns the minimum priority relative to \c Compare.
185
    /// \brief The minimum priority.
180 186
    ///
181
    /// It returns the minimum priority relative to \c Compare.
182
    /// \pre The heap must be nonempty.
183
    const Prio& prio() const { return container[minimum].prio; }
187
    /// This function returns the minimum priority.
188
    /// \pre The heap must be non-empty.
189
    Prio prio() const { return _data[_min].prio; }
184 190

	
185
    /// \brief Returns the priority of \c item.
191
    /// \brief The priority of the given item.
186 192
    ///
187
    /// It returns the priority of \c item.
188
    /// \pre \c item must be in the heap.
193
    /// This function returns the priority of the given item.
194
    /// \param item The item.
195
    /// \pre \e item must be in the heap.
189 196
    const Prio& operator[](const Item& item) const {
190
      return container[iimap[item]].prio;
197
      return _data[_iim[item]].prio;
191 198
    }
192 199

	
193
    /// \brief Deletes the item with minimum priority relative to \c Compare.
200
    /// \brief Remove the item having minimum priority.
194 201
    ///
195
    /// This method deletes the item with minimum priority relative to \c
196
    /// Compare from the heap.
202
    /// This function removes the item having minimum priority.
197 203
    /// \pre The heap must be non-empty.
198 204
    void pop() {
199
      container[minimum].in=false;
205
      _data[_min].in=false;
200 206

	
201 207
      int head_child=-1;
202
      if ( container[minimum].child!=-1 ) {
203
        int child=container[minimum].child;
208
      if ( _data[_min].child!=-1 ) {
209
        int child=_data[_min].child;
204 210
        int neighb;
205 211
        int prev=-1;
206 212
        while( child!=-1 ) {
207
          neighb=container[child].right_neighbor;
208
          container[child].parent=-1;
209
          container[child].right_neighbor=prev;
213
          neighb=_data[child].right_neighbor;
214
          _data[child].parent=-1;
215
          _data[child].right_neighbor=prev;
210 216
          head_child=child;
211 217
          prev=child;
212 218
          child=neighb;
213 219
        }
214 220
      }
215 221

	
216 222
      // The first case is that there are only one root.
217
      if ( -1==container[head].right_neighbor ) {
218
        head=head_child;
223
      if ( -1==_data[_head].right_neighbor ) {
224
        _head=head_child;
219 225
      }
220 226
      // The case where there are more roots.
221 227
      else {
222
        if( head!=minimum )  { unlace(minimum); }
223
        else { head=container[head].right_neighbor; }
228
        if( _head!=_min )  { unlace(_min); }
229
        else { _head=_data[_head].right_neighbor; }
224 230

	
225 231
        merge(head_child);
226 232
      }
227
      minimum=find_min();
228
      --num_items;
233
      _min=findMin();
234
      --_num_items;
229 235
    }
230 236

	
231
    /// \brief Deletes \c item from the heap.
237
    /// \brief Remove the given item from the heap.
232 238
    ///
233
    /// This method deletes \c item from the heap, if \c item was already
234
    /// stored in the heap. It is quite inefficient in Binomial heaps.
239
    /// This function removes the given item from the heap if it is
240
    /// already stored.
241
    /// \param item The item to delete.
242
    /// \pre \e item must be in the heap.
235 243
    void erase (const Item& item) {
236
      int i=iimap[item];
237
      if ( i >= 0 && container[i].in ) {
238
        decrease( item, container[minimum].prio-1 );
244
      int i=_iim[item];
245
      if ( i >= 0 && _data[i].in ) {
246
        decrease( item, _data[_min].prio-1 );
239 247
        pop();
240 248
      }
241 249
    }
242 250

	
243
    /// \brief Decreases the priority of \c item to \c value.
251
    /// \brief Decrease the priority of an item to the given value.
244 252
    ///
245
    /// This method decreases the priority of \c item to \c value.
246
    /// \pre \c item must be stored in the heap with priority at least \c
247
    ///   value relative to \c Compare.
253
    /// This function decreases the priority of an item to the given value.
254
    /// \param item The item.
255
    /// \param value The priority.
256
    /// \pre \e item must be stored in the heap with priority at least \e value.
248 257
    void decrease (Item item, const Prio& value) {
249
      int i=iimap[item];
258
      int i=_iim[item];
250 259

	
251
      if( comp( value,container[i].prio ) ) {
252
        container[i].prio=value;
260
      if( _comp( value,_data[i].prio ) ) {
261
        _data[i].prio=value;
253 262

	
254
        int p_loc=container[i].parent, loc=i;
263
        int p_loc=_data[i].parent, loc=i;
255 264
        int parent, child, neighb;
256 265

	
257
        while( -1!=p_loc && comp(container[loc].prio,container[p_loc].prio) ) {
266
        while( -1!=p_loc && _comp(_data[loc].prio,_data[p_loc].prio) ) {
258 267

	
259 268
          // parent set for other loc_child
260
          child=container[loc].child;
269
          child=_data[loc].child;
261 270
          while( -1!=child ) {
262
            container[child].parent=p_loc;
263
            child=container[child].right_neighbor;
271
            _data[child].parent=p_loc;
272
            child=_data[child].right_neighbor;
264 273
          }
265 274

	
266 275
          // parent set for other p_loc_child
267
          child=container[p_loc].child;
276
          child=_data[p_loc].child;
268 277
          while( -1!=child ) {
269
            container[child].parent=loc;
270
            child=container[child].right_neighbor;
278
            _data[child].parent=loc;
279
            child=_data[child].right_neighbor;
271 280
          }
272 281

	
273
          child=container[p_loc].child;
274
          container[p_loc].child=container[loc].child;
282
          child=_data[p_loc].child;
283
          _data[p_loc].child=_data[loc].child;
275 284
          if( child==loc )
276 285
            child=p_loc;
277
          container[loc].child=child;
286
          _data[loc].child=child;
278 287

	
279 288
          // left_neighb set for p_loc
280
          if( container[loc].child!=p_loc ) {
281
            while( container[child].right_neighbor!=loc )
282
              child=container[child].right_neighbor;
283
            container[child].right_neighbor=p_loc;
289
          if( _data[loc].child!=p_loc ) {
290
            while( _data[child].right_neighbor!=loc )
291
              child=_data[child].right_neighbor;
292
            _data[child].right_neighbor=p_loc;
284 293
          }
285 294

	
286 295
          // left_neighb set for loc
287
          parent=container[p_loc].parent;
288
          if( -1!=parent ) child=container[parent].child;
289
          else child=head;
296
          parent=_data[p_loc].parent;
297
          if( -1!=parent ) child=_data[parent].child;
298
          else child=_head;
290 299

	
291 300
          if( child!=p_loc ) {
292
            while( container[child].right_neighbor!=p_loc )
293
              child=container[child].right_neighbor;
294
            container[child].right_neighbor=loc;
301
            while( _data[child].right_neighbor!=p_loc )
302
              child=_data[child].right_neighbor;
303
            _data[child].right_neighbor=loc;
295 304
          }
296 305

	
297
          neighb=container[p_loc].right_neighbor;
298
          container[p_loc].right_neighbor=container[loc].right_neighbor;
299
          container[loc].right_neighbor=neighb;
306
          neighb=_data[p_loc].right_neighbor;
307
          _data[p_loc].right_neighbor=_data[loc].right_neighbor;
308
          _data[loc].right_neighbor=neighb;
300 309

	
301
          container[p_loc].parent=loc;
302
          container[loc].parent=parent;
310
          _data[p_loc].parent=loc;
311
          _data[loc].parent=parent;
303 312

	
304
          if( -1!=parent && container[parent].child==p_loc )
305
            container[parent].child=loc;
313
          if( -1!=parent && _data[parent].child==p_loc )
314
            _data[parent].child=loc;
306 315

	
307 316
          /*if new parent will be the first root*/
308
          if( head==p_loc )
309
            head=loc;
317
          if( _head==p_loc )
318
            _head=loc;
310 319

	
311
          p_loc=container[loc].parent;
320
          p_loc=_data[loc].parent;
312 321
        }
313 322
      }
314
      if( comp(value,container[minimum].prio) ) {
315
        minimum=i;
323
      if( _comp(value,_data[_min].prio) ) {
324
        _min=i;
316 325
      }
317 326
    }
318 327

	
319
    /// \brief Increases the priority of \c item to \c value.
328
    /// \brief Increase the priority of an item to the given value.
320 329
    ///
321
    /// This method sets the priority of \c item to \c value. Though
322
    /// there is no precondition on the priority of \c item, this
323
    /// method should be used only if it is indeed necessary to increase
324
    /// (relative to \c Compare) the priority of \c item, because this
325
    /// method is inefficient.
330
    /// This function increases the priority of an item to the given value.
331
    /// \param item The item.
332
    /// \param value The priority.
333
    /// \pre \e item must be stored in the heap with priority at most \e value.
326 334
    void increase (Item item, const Prio& value) {
327 335
      erase(item);
328 336
      push(item, value);
329 337
    }
330 338

	
331

	
332
    /// \brief Returns if \c item is in, has already been in, or has never
333
    /// been in the heap.
339
    /// \brief Return the state of an item.
334 340
    ///
335
    /// This method returns PRE_HEAP if \c item has never been in the
336
    /// heap, IN_HEAP if it is in the heap at the moment, and POST_HEAP
337
    /// otherwise. In the latter case it is possible that \c item will
338
    /// get back to the heap again.
341
    /// This method returns \c PRE_HEAP if the given item has never
342
    /// been in the heap, \c IN_HEAP if it is in the heap at the moment,
343
    /// and \c POST_HEAP otherwise.
344
    /// In the latter case it is possible that the item will get back
345
    /// to the heap again.
346
    /// \param item The item.
339 347
    State state(const Item &item) const {
340
      int i=iimap[item];
348
      int i=_iim[item];
341 349
      if( i>=0 ) {
342
        if ( container[i].in ) i=0;
350
        if ( _data[i].in ) i=0;
343 351
        else i=-2;
344 352
      }
345 353
      return State(i);
346 354
    }
347 355

	
348
    /// \brief Sets the state of the \c item in the heap.
356
    /// \brief Set the state of an item in the heap.
349 357
    ///
350
    /// Sets the state of the \c item in the heap. It can be used to
351
    /// manually clear the heap when it is important to achive the
352
    /// better time complexity.
358
    /// This function sets the state of the given item in the heap.
359
    /// It can be used to manually clear the heap when it is important
360
    /// to achive better time complexity.
353 361
    /// \param i The item.
354 362
    /// \param st The state. It should not be \c IN_HEAP.
355 363
    void state(const Item& i, State st) {
356 364
      switch (st) {
357 365
      case POST_HEAP:
358 366
      case PRE_HEAP:
359 367
        if (state(i) == IN_HEAP) {
360 368
          erase(i);
361 369
        }
362
        iimap[i] = st;
370
        _iim[i] = st;
363 371
        break;
364 372
      case IN_HEAP:
365 373
        break;
366 374
      }
367 375
    }
368 376

	
369 377
  private:
370
    int find_min() {
378
    int findMin() {
371 379
      int min_loc=-1, min_val;
372
      int x=head;
380
      int x=_head;
373 381
      if( x!=-1 ) {
374
        min_val=container[x].prio;
382
        min_val=_data[x].prio;
375 383
        min_loc=x;
376
        x=container[x].right_neighbor;
384
        x=_data[x].right_neighbor;
377 385

	
378 386
        while( x!=-1 ) {
379
          if( comp( container[x].prio,min_val ) ) {
380
            min_val=container[x].prio;
387
          if( _comp( _data[x].prio,min_val ) ) {
388
            min_val=_data[x].prio;
381 389
            min_loc=x;
382 390
          }
383
          x=container[x].right_neighbor;
391
          x=_data[x].right_neighbor;
384 392
        }
385 393
      }
386 394
      return min_loc;
387 395
    }
388 396

	
389 397
    void merge(int a) {
390 398
      interleave(a);
391 399

	
392
      int x=head;
400
      int x=_head;
393 401
      if( -1!=x ) {
394
        int x_prev=-1, x_next=container[x].right_neighbor;
402
        int x_prev=-1, x_next=_data[x].right_neighbor;
395 403
        while( -1!=x_next ) {
396
          if( container[x].degree!=container[x_next].degree || ( -1!=container[x_next].right_neighbor && container[container[x_next].right_neighbor].degree==container[x].degree ) ) {
404
          if( _data[x].degree!=_data[x_next].degree || ( -1!=_data[x_next].right_neighbor && _data[_data[x_next].right_neighbor].degree==_data[x].degree ) ) {
397 405
            x_prev=x;
398 406
            x=x_next;
399 407
          }
400 408
          else {
401
            if( comp(container[x].prio,container[x_next].prio) ) {
402
              container[x].right_neighbor=container[x_next].right_neighbor;
409
            if( _comp(_data[x].prio,_data[x_next].prio) ) {
410
              _data[x].right_neighbor=_data[x_next].right_neighbor;
403 411
              fuse(x_next,x);
404 412
            }
405 413
            else {
406
              if( -1==x_prev ) { head=x_next; }
414
              if( -1==x_prev ) { _head=x_next; }
407 415
              else {
408
                container[x_prev].right_neighbor=x_next;
416
                _data[x_prev].right_neighbor=x_next;
409 417
              }
410 418
              fuse(x,x_next);
411 419
              x=x_next;
412 420
            }
413 421
          }
414
          x_next=container[x].right_neighbor;
422
          x_next=_data[x].right_neighbor;
415 423
        }
416 424
      }
417 425
    }
418 426

	
419 427
    void interleave(int a) {
420 428
      int other=-1, head_other=-1;
421 429

	
422
      while( -1!=a || -1!=head ) {
430
      while( -1!=a || -1!=_head ) {
423 431
        if( -1==a ) {
424 432
          if( -1==head_other ) {
425
            head_other=head;
433
            head_other=_head;
426 434
          }
427 435
          else {
428
            container[other].right_neighbor=head;
436
            _data[other].right_neighbor=_head;
429 437
          }
430
          head=-1;
438
          _head=-1;
431 439
        }
432
        else if( -1==head ) {
440
        else if( -1==_head ) {
433 441
          if( -1==head_other ) {
434 442
            head_other=a;
435 443
          }
436 444
          else {
437
            container[other].right_neighbor=a;
445
            _data[other].right_neighbor=a;
438 446
          }
439 447
          a=-1;
440 448
        }
441 449
        else {
442
          if( container[a].degree<container[head].degree ) {
450
          if( _data[a].degree<_data[_head].degree ) {
443 451
            if( -1==head_other ) {
444 452
              head_other=a;
445 453
            }
446 454
            else {
447
              container[other].right_neighbor=a;
455
              _data[other].right_neighbor=a;
448 456
            }
449 457
            other=a;
450
            a=container[a].right_neighbor;
458
            a=_data[a].right_neighbor;
451 459
          }
452 460
          else {
453 461
            if( -1==head_other ) {
454
              head_other=head;
462
              head_other=_head;
455 463
            }
456 464
            else {
457
              container[other].right_neighbor=head;
465
              _data[other].right_neighbor=_head;
458 466
            }
459
            other=head;
460
            head=container[head].right_neighbor;
467
            other=_head;
468
            _head=_data[_head].right_neighbor;
461 469
          }
462 470
        }
463 471
      }
464
      head=head_other;
472
      _head=head_other;
465 473
    }
466 474

	
467 475
    // Lacing a under b
468 476
    void fuse(int a, int b) {
469
      container[a].parent=b;
470
      container[a].right_neighbor=container[b].child;
471
      container[b].child=a;
477
      _data[a].parent=b;
478
      _data[a].right_neighbor=_data[b].child;
479
      _data[b].child=a;
472 480

	
473
      ++container[b].degree;
481
      ++_data[b].degree;
474 482
    }
475 483

	
476 484
    // It is invoked only if a has siblings.
477 485
    void unlace(int a) {
478
      int neighb=container[a].right_neighbor;
479
      int other=head;
486
      int neighb=_data[a].right_neighbor;
487
      int other=_head;
480 488

	
481
      while( container[other].right_neighbor!=a )
482
        other=container[other].right_neighbor;
483
      container[other].right_neighbor=neighb;
489
      while( _data[other].right_neighbor!=a )
490
        other=_data[other].right_neighbor;
491
      _data[other].right_neighbor=neighb;
484 492
    }
485 493

	
486 494
  private:
487 495

	
488 496
    class store {
489 497
      friend class BinomHeap;
490 498

	
491 499
      Item name;
492 500
      int parent;
493 501
      int right_neighbor;
494 502
      int child;
495 503
      int degree;
496 504
      bool in;
497 505
      Prio prio;
498 506

	
499 507
      store() : parent(-1), right_neighbor(-1), child(-1), degree(0), in(true) {}
500 508
    };
501 509
  };
502 510

	
503 511
} //namespace lemon
504 512

	
505 513
#endif //LEMON_BINOM_HEAP_H
506 514

	
Ignore white space 6 line context
1
/* -*- C++ -*-
1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 2
 *
3
 * This file is a part of LEMON, a generic C++ optimization library
3
 * This file is a part of LEMON, a generic C++ optimization library.
4 4
 *
5
 * Copyright (C) 2003-2008
5
 * Copyright (C) 2003-2009
6 6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 8
 *
9 9
 * Permission to use, modify and distribute this software is granted
10 10
 * provided that this copyright notice appears in all copies. For
11 11
 * precise terms see the accompanying LICENSE file.
12 12
 *
13 13
 * This software is provided "AS IS" with no warranty of any kind,
14 14
 * express or implied, and with no claim as to its suitability for any
15 15
 * purpose.
16 16
 *
17 17
 */
18 18

	
19 19
#ifndef LEMON_FOURARY_HEAP_H
20 20
#define LEMON_FOURARY_HEAP_H
21 21

	
22
///\ingroup auxdat
22
///\ingroup heaps
23 23
///\file
24
///\brief 4ary Heap implementation.
24
///\brief Fourary heap implementation.
25 25

	
26
#include <iostream>
27 26
#include <vector>
28 27
#include <utility>
29 28
#include <functional>
30 29

	
31 30
namespace lemon {
32 31

	
33
  ///\ingroup auxdat
32
  /// \ingroup heaps
34 33
  ///
35
  ///\brief A 4ary Heap implementation.
34
  ///\brief Fourary heap data structure.
36 35
  ///
37
  ///This class implements the \e 4ary \e heap data structure. A \e heap
38
  ///is a data structure for storing items with specified values called \e
39
  ///priorities in such a way that finding the item with minimum priority is
40
  ///efficient. \c Compare specifies the ordering of the priorities. In a heap
41
  ///one can change the priority of an item, add or erase an item, etc.
36
  /// This class implements the \e fourary \e heap data structure.
37
  /// It fully conforms to the \ref concepts::Heap "heap concept".
42 38
  ///
43
  ///\param _Prio Type of the priority of the items.
44
  ///\param _ItemIntMap A read and writable Item int map, used internally
45
  ///to handle the cross references.
46
  ///\param _Compare A class for the ordering of the priorities. The
47
  ///default is \c std::less<_Prio>.
39
  /// The fourary heap is a specialization of the \ref KaryHeap "K-ary heap"
40
  /// for <tt>K=4</tt>. It is similar to the \ref BinHeap "binary heap",
41
  /// but its nodes have at most four children, instead of two.
48 42
  ///
49
  ///\sa FibHeap
50
  ///\sa Dijkstra
51
  ///\author Dorian Batha
43
  /// \tparam PR Type of the priorities of the items.
44
  /// \tparam IM A read-writable item map with \c int values, used
45
  /// internally to handle the cross references.
46
  /// \tparam CMP A functor class for comparing the priorities.
47
  /// The default is \c std::less<PR>.
48
  ///
49
  ///\sa BinHeap
50
  ///\sa KaryHeap
51
#ifdef DOXYGEN
52
  template <typename PR, typename IM, typename CMP>
53
#else
54
  template <typename PR, typename IM, typename CMP = std::less<PR> >
55
#endif
56
  class FouraryHeap {
57
  public:
58
    /// Type of the item-int map.
59
    typedef IM ItemIntMap;
60
    /// Type of the priorities.
61
    typedef PR Prio;
62
    /// Type of the items stored in the heap.
63
    typedef typename ItemIntMap::Key Item;
64
    /// Type of the item-priority pairs.
65
    typedef std::pair<Item,Prio> Pair;
66
    /// Functor type for comparing the priorities.
67
    typedef CMP Compare;
52 68

	
53
  template <typename _Prio, typename _ItemIntMap,
54
            typename _Compare = std::less<_Prio> >
55

	
56
  class FouraryHeap {
57

	
58
  public:
59
    ///\e
60
    typedef _ItemIntMap ItemIntMap;
61
    ///\e
62
    typedef _Prio Prio;
63
    ///\e
64
    typedef typename ItemIntMap::Key Item;
65
    ///\e
66
    typedef std::pair<Item,Prio> Pair;
67
    ///\e
68
    typedef _Compare Compare;
69

	
70
    /// \brief Type to represent the items states.
69
    /// \brief Type to represent the states of the items.
71 70
    ///
72
    /// Each Item element have a state associated to it. It may be "in heap",
73
    /// "pre heap" or "post heap". The latter two are indifferent from the
71
    /// Each item has a state associated to it. It can be "in heap",
72
    /// "pre-heap" or "post-heap". The latter two are indifferent from the
74 73
    /// heap's point of view, but may be useful to the user.
75 74
    ///
76
    /// The ItemIntMap \e should be initialized in such way that it maps
77
    /// PRE_HEAP (-1) to any element to be put in the heap...
75
    /// The item-int map must be initialized in such way that it assigns
76
    /// \c PRE_HEAP (<tt>-1</tt>) to any element to be put in the heap.
78 77
    enum State {
79
      IN_HEAP = 0,
80
      PRE_HEAP = -1,
81
      POST_HEAP = -2
78
      IN_HEAP = 0,    ///< = 0.
79
      PRE_HEAP = -1,  ///< = -1.
80
      POST_HEAP = -2  ///< = -2.
82 81
    };
83 82

	
84 83
  private:
85
    std::vector<Pair> data;
86
    Compare comp;
87
    ItemIntMap &iim;
84
    std::vector<Pair> _data;
85
    Compare _comp;
86
    ItemIntMap &_iim;
88 87

	
89 88
  public:
90
    /// \brief The constructor.
89
    /// \brief Constructor.
91 90
    ///
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
    explicit FouraryHeap(ItemIntMap &_iim) : iim(_iim) {}
91
    /// Constructor.
92
    /// \param map A map that assigns \c int values to the items.
93
    /// It is used internally to handle the cross references.
94
    /// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
95
    explicit FouraryHeap(ItemIntMap &map) : _iim(map) {}
97 96

	
98
    /// \brief The constructor.
97
    /// \brief Constructor.
99 98
    ///
100
    /// The constructor.
101
    /// \param _iim should be given to the constructor, since it is used
102
    /// internally to handle the cross references. The value of the map
103
    /// should be PRE_HEAP (-1) for each element.
99
    /// Constructor.
100
    /// \param map A map that assigns \c int values to the items.
101
    /// It is used internally to handle the cross references.
102
    /// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
103
    /// \param comp The function object used for comparing the priorities.
104
    FouraryHeap(ItemIntMap &map, const Compare &comp)
105
      : _iim(map), _comp(comp) {}
106

	
107
    /// \brief The number of items stored in the heap.
104 108
    ///
105
    /// \param _comp The comparator function object.
106
    FouraryHeap(ItemIntMap &_iim, const Compare &_comp)
107
      : iim(_iim), comp(_comp) {}
109
    /// This function returns the number of items stored in the heap.
110
    int size() const { return _data.size(); }
108 111

	
109
    /// The number of items stored in the heap.
112
    /// \brief Check if the heap is empty.
110 113
    ///
111
    /// \brief Returns the number of items stored in the heap.
112
    int size() const { return data.size(); }
114
    /// This function returns \c true if the heap is empty.
115
    bool empty() const { return _data.empty(); }
113 116

	
114
    /// \brief Checks if the heap stores no items.
117
    /// \brief Make the heap empty.
115 118
    ///
116
    /// Returns \c true if and only if the heap stores no items.
117
    bool empty() const { return data.empty(); }
118

	
119
    /// \brief Make empty this heap.
120
    ///
121
    /// Make empty this heap. It does not change the cross reference map.
122
    /// If you want to reuse what is not surely empty you should first clear
123
    /// the heap and after that you should set the cross reference map for
124
    /// each item to \c PRE_HEAP.
125
    void clear() { data.clear(); }
119
    /// This functon makes the heap empty.
120
    /// It does not change the cross reference map. If you want to reuse
121
    /// a heap that is not surely empty, you should first clear it and
122
    /// then you should set the cross reference map to \c PRE_HEAP
123
    /// for each item.
124
    void clear() { _data.clear(); }
126 125

	
127 126
  private:
128 127
    static int parent(int i) { return (i-1)/4; }
129 128
    static int firstChild(int i) { return 4*i+1; }
130 129

	
131 130
    bool less(const Pair &p1, const Pair &p2) const {
132
      return comp(p1.second, p2.second);
131
      return _comp(p1.second, p2.second);
133 132
    }
134 133

	
135
    int find_min(const int child, const int length) {
134
    int findMin(const int child, const int length) {
136 135
      int min=child;
137 136
      if( child+3<length ) {
138
        if( less(data[child+3], data[min]) )
137
        if( less(_data[child+3], _data[min]) )
139 138
          min=child+3;
140
        if( less(data[child+2], data[min]) )
139
        if( less(_data[child+2], _data[min]) )
141 140
          min=child+2;
142
        if( less(data[child+1], data[min]) )
141
        if( less(_data[child+1], _data[min]) )
143 142
          min=child+1;
144 143
      }
145 144
      else if( child+2<length ) {
146
        if( less(data[child+2], data[min]) )
145
        if( less(_data[child+2], _data[min]) )
147 146
          min=child+2;
148
        if( less(data[child+1], data[min]) )
147
        if( less(_data[child+1], _data[min]) )
149 148
          min=child+1;
150 149
      }
151 150
      else if( child+1<length ) {
152
        if( less(data[child+1], data[min]) )
151
        if( less(_data[child+1], _data[min]) )
153 152
          min=child+1;
154 153
      }
155 154
      return min;
156 155
    }
157 156

	
158
    void bubble_up(int hole, Pair p) {
157
    void bubbleUp(int hole, Pair p) {
159 158
      int par = parent(hole);
160
      while( hole>0 && less(p,data[par]) ) {
161
        move(data[par],hole);
159
      while( hole>0 && less(p,_data[par]) ) {
160
        move(_data[par],hole);
162 161
        hole = par;
163 162
        par = parent(hole);
164 163
      }
165 164
      move(p, hole);
166 165
    }
167 166

	
168
    void bubble_down(int hole, Pair p, int length) {
167
    void bubbleDown(int hole, Pair p, int length) {
169 168
      int child = firstChild(hole);
170 169
      while( child<length && length>1 ) {
171
        child = find_min(child,length);
172
        if( !less(data[child], p) )
170
        child = findMin(child,length);
171
        if( !less(_data[child], p) )
173 172
          goto ok;
174
        move(data[child], hole);
173
        move(_data[child], hole);
175 174
        hole = child;
176 175
        child = firstChild(hole);
177 176
      }
178 177
    ok:
179 178
      move(p, hole);
180 179
    }
181 180

	
182 181
    void move(const Pair &p, int i) {
183
      data[i] = p;
184
      iim.set(p.first, i);
182
      _data[i] = p;
183
      _iim.set(p.first, i);
185 184
    }
186 185

	
187 186
  public:
188

	
189 187
    /// \brief Insert a pair of item and priority into the heap.
190 188
    ///
191
    /// Adds \c p.first to the heap with priority \c p.second.
189
    /// This function inserts \c p.first to the heap with priority
190
    /// \c p.second.
192 191
    /// \param p The pair to insert.
192
    /// \pre \c p.first must not be stored in the heap.
193 193
    void push(const Pair &p) {
194
      int n = data.size();
195
      data.resize(n+1);
196
      bubble_up(n, p);
194
      int n = _data.size();
195
      _data.resize(n+1);
196
      bubbleUp(n, p);
197 197
    }
198 198

	
199
    /// \brief Insert an item into the heap with the given heap.
199
    /// \brief Insert an item into the heap with the given priority.
200 200
    ///
201
    /// Adds \c i to the heap with priority \c p.
201
    /// This function inserts the given item into the heap with the
202
    /// given priority.
202 203
    /// \param i The item to insert.
203 204
    /// \param p The priority of the item.
205
    /// \pre \e i must not be stored in the heap.
204 206
    void push(const Item &i, const Prio &p) { push(Pair(i,p)); }
205 207

	
206
    /// \brief Returns the item with minimum priority relative to \c Compare.
208
    /// \brief Return the item having minimum priority.
207 209
    ///
208
    /// This method returns the item with minimum priority relative to \c
209
    /// Compare.
210
    /// \pre The heap must be nonempty.
211
    Item top() const { return data[0].first; }
210
    /// This function returns the item having minimum priority.
211
    /// \pre The heap must be non-empty.
212
    Item top() const { return _data[0].first; }
212 213

	
213
    /// \brief Returns the minimum priority relative to \c Compare.
214
    /// \brief The minimum priority.
214 215
    ///
215
    /// It returns the minimum priority relative to \c Compare.
216
    /// \pre The heap must be nonempty.
217
    Prio prio() const { return data[0].second; }
216
    /// This function returns the minimum priority.
217
    /// \pre The heap must be non-empty.
218
    Prio prio() const { return _data[0].second; }
218 219

	
219
    /// \brief Deletes the item with minimum priority relative to \c Compare.
220
    /// \brief Remove the item having minimum priority.
220 221
    ///
221
    /// This method deletes the item with minimum priority relative to \c
222
    /// Compare from the heap.
222
    /// This function removes the item having minimum priority.
223 223
    /// \pre The heap must be non-empty.
224 224
    void pop() {
225
      int n = data.size()-1;
226
      iim.set(data[0].first, POST_HEAP);
227
      if (n>0) bubble_down(0, data[n], n);
228
      data.pop_back();
225
      int n = _data.size()-1;
226
      _iim.set(_data[0].first, POST_HEAP);
227
      if (n>0) bubbleDown(0, _data[n], n);
228
      _data.pop_back();
229 229
    }
230 230

	
231
    /// \brief Deletes \c i from the heap.
231
    /// \brief Remove the given item from the heap.
232 232
    ///
233
    /// This method deletes item \c i from the heap.
234
    /// \param i The item to erase.
235
    /// \pre The item should be in the heap.
233
    /// This function removes the given item from the heap if it is
234
    /// already stored.
235
    /// \param i The item to delete.
236
    /// \pre \e i must be in the heap.
236 237
    void erase(const Item &i) {
237
      int h = iim[i];
238
      int n = data.size()-1;
239
      iim.set(data[h].first, POST_HEAP);
238
      int h = _iim[i];
239
      int n = _data.size()-1;
240
      _iim.set(_data[h].first, POST_HEAP);
240 241
      if( h<n ) {
241
        if( less(data[parent(h)], data[n]) )
242
          bubble_down(h, data[n], n);
242
        if( less(_data[parent(h)], _data[n]) )
243
          bubbleDown(h, _data[n], n);
243 244
        else
244
          bubble_up(h, data[n]);
245
          bubbleUp(h, _data[n]);
245 246
      }
246
      data.pop_back();
247
      _data.pop_back();
247 248
    }
248 249

	
249
    /// \brief Returns the priority of \c i.
250
    /// \brief The priority of the given item.
250 251
    ///
251
    /// This function returns the priority of item \c i.
252
    /// \pre \c i must be in the heap.
252
    /// This function returns the priority of the given item.
253 253
    /// \param i The item.
254
    /// \pre \e i must be in the heap.
254 255
    Prio operator[](const Item &i) const {
255
      int idx = iim[i];
256
      return data[idx].second;
256
      int idx = _iim[i];
257
      return _data[idx].second;
257 258
    }
258 259

	
259
    /// \brief \c i gets to the heap with priority \c p independently
260
    /// if \c i was already there.
260
    /// \brief Set the priority of an item or insert it, if it is
261
    /// not stored in the heap.
261 262
    ///
262
    /// This method calls \ref push(\c i, \c p) if \c i is not stored
263
    /// in the heap and sets the priority of \c i to \c p otherwise.
263
    /// This method sets the priority of the given item if it is
264
    /// already stored in the heap. Otherwise it inserts the given
265
    /// item into the heap with the given priority.
264 266
    /// \param i The item.
265 267
    /// \param p The priority.
266 268
    void set(const Item &i, const Prio &p) {
267
      int idx = iim[i];
269
      int idx = _iim[i];
268 270
      if( idx < 0 )
269 271
        push(i,p);
270
      else if( comp(p, data[idx].second) )
271
        bubble_up(idx, Pair(i,p));
272
      else if( _comp(p, _data[idx].second) )
273
        bubbleUp(idx, Pair(i,p));
272 274
      else
273
        bubble_down(idx, Pair(i,p), data.size());
275
        bubbleDown(idx, Pair(i,p), _data.size());
274 276
    }
275 277

	
276
    /// \brief Decreases the priority of \c i to \c p.
278
    /// \brief Decrease the priority of an item to the given value.
277 279
    ///
278
    /// This method decreases the priority of item \c i to \c p.
279
    /// \pre \c i must be stored in the heap with priority at least \c
280
    /// p relative to \c Compare.
280
    /// This function decreases the priority of an item to the given value.
281 281
    /// \param i The item.
282 282
    /// \param p The priority.
283
    /// \pre \e i must be stored in the heap with priority at least \e p.
283 284
    void decrease(const Item &i, const Prio &p) {
284
      int idx = iim[i];
285
      bubble_up(idx, Pair(i,p));
285
      int idx = _iim[i];
286
      bubbleUp(idx, Pair(i,p));
286 287
    }
287 288

	
288
    /// \brief Increases the priority of \c i to \c p.
289
    /// \brief Increase the priority of an item to the given value.
289 290
    ///
290
    /// This method sets the priority of item \c i to \c p.
291
    /// \pre \c i must be stored in the heap with priority at most \c
292
    /// p relative to \c Compare.
291
    /// This function increases the priority of an item to the given value.
293 292
    /// \param i The item.
294 293
    /// \param p The priority.
294
    /// \pre \e i must be stored in the heap with priority at most \e p.
295 295
    void increase(const Item &i, const Prio &p) {
296
      int idx = iim[i];
297
      bubble_down(idx, Pair(i,p), data.size());
296
      int idx = _iim[i];
297
      bubbleDown(idx, Pair(i,p), _data.size());
298 298
    }
299 299

	
300
    /// \brief Returns if \c item is in, has already been in, or has
301
    /// never been in the heap.
300
    /// \brief Return the state of an item.
302 301
    ///
303
    /// This method returns PRE_HEAP if \c item has never been in the
304
    /// heap, IN_HEAP if it is in the heap at the moment, and POST_HEAP
305
    /// otherwise. In the latter case it is possible that \c item will
306
    /// get back to the heap again.
302
    /// This method returns \c PRE_HEAP if the given item has never
303
    /// been in the heap, \c IN_HEAP if it is in the heap at the moment,
304
    /// and \c POST_HEAP otherwise.
305
    /// In the latter case it is possible that the item will get back
306
    /// to the heap again.
307 307
    /// \param i The item.
308 308
    State state(const Item &i) const {
309
      int s = iim[i];
309
      int s = _iim[i];
310 310
      if (s>=0) s=0;
311 311
      return State(s);
312 312
    }
313 313

	
314
    /// \brief Sets the state of the \c item in the heap.
314
    /// \brief Set the state of an item in the heap.
315 315
    ///
316
    /// Sets the state of the \c item in the heap. It can be used to
317
    /// manually clear the heap when it is important to achive the
318
    /// better time complexity.
316
    /// This function sets the state of the given item in the heap.
317
    /// It can be used to manually clear the heap when it is important
318
    /// to achive better time complexity.
319 319
    /// \param i The item.
320 320
    /// \param st The state. It should not be \c IN_HEAP.
321 321
    void state(const Item& i, State st) {
322 322
      switch (st) {
323 323
        case POST_HEAP:
324 324
        case PRE_HEAP:
325 325
          if (state(i) == IN_HEAP) erase(i);
326
          iim[i] = st;
326
          _iim[i] = st;
327 327
          break;
328 328
        case IN_HEAP:
329 329
          break;
330 330
      }
331 331
    }
332 332

	
333
    /// \brief Replaces an item in the heap.
333
    /// \brief Replace an item in the heap.
334 334
    ///
335
    /// The \c i item is replaced with \c j item. The \c i item should
336
    /// be in the heap, while the \c j should be out of the heap. The
337
    /// \c i item will out of the heap and \c j will be in the heap
338
    /// with the same prioriority as prevoiusly the \c i item.
335
    /// This function replaces item \c i with item \c j.
336
    /// Item \c i must be in the heap, while \c j must be out of the heap.
337
    /// After calling this method, item \c i will be out of the
338
    /// heap and \c j will be in the heap with the same prioriority
339
    /// as item \c i had before.
339 340
    void replace(const Item& i, const Item& j) {
340
      int idx = iim[i];
341
      iim.set(i, iim[j]);
342
      iim.set(j, idx);
343
      data[idx].first = j;
341
      int idx = _iim[i];
342
      _iim.set(i, _iim[j]);
343
      _iim.set(j, idx);
344
      _data[idx].first = j;
344 345
    }
345 346

	
346 347
  }; // class FouraryHeap
347 348

	
348 349
} // namespace lemon
349 350

	
350 351
#endif // LEMON_FOURARY_HEAP_H
Ignore white space 6291456 line context
1
/* -*- C++ -*-
1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 2
 *
3
 * This file is a part of LEMON, a generic C++ optimization library
3
 * This file is a part of LEMON, a generic C++ optimization library.
4 4
 *
5
 * Copyright (C) 2003-2008
5
 * Copyright (C) 2003-2009
6 6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 8
 *
9 9
 * Permission to use, modify and distribute this software is granted
10 10
 * provided that this copyright notice appears in all copies. For
11 11
 * precise terms see the accompanying LICENSE file.
12 12
 *
13 13
 * This software is provided "AS IS" with no warranty of any kind,
14 14
 * express or implied, and with no claim as to its suitability for any
15 15
 * purpose.
16 16
 *
17 17
 */
18 18

	
19 19
#ifndef LEMON_KARY_HEAP_H
20 20
#define LEMON_KARY_HEAP_H
21 21

	
22
///\ingroup auxdat
22
///\ingroup heaps
23 23
///\file
24
///\brief Kary Heap implementation.
24
///\brief Fourary heap implementation.
25 25

	
26
#include <iostream>
27 26
#include <vector>
28 27
#include <utility>
29 28
#include <functional>
30 29

	
31 30
namespace lemon {
32 31

	
33
  ///\ingroup auxdat
32
  /// \ingroup heaps
34 33
  ///
35
  ///\brief A Kary Heap implementation.
34
  ///\brief K-ary heap data structure.
36 35
  ///
37
  ///This class implements the \e Kary \e heap data structure. A \e heap
38
  ///is a data structure for storing items with specified values called \e
39
  ///priorities in such a way that finding the item with minimum priority is
40
  ///efficient. \c Compare specifies the ordering of the priorities. In a heap
41
  ///one can change the priority of an item, add or erase an item, etc.
36
  /// This class implements the \e K-ary \e heap data structure.
37
  /// It fully conforms to the \ref concepts::Heap "heap concept".
42 38
  ///
43
  ///\param _Prio Type of the priority of the items.
44
  ///\param _ItemIntMap A read and writable Item int map, used internally
45
  ///to handle the cross references.
46
  ///\param _Compare A class for the ordering of the priorities. The
47
  ///default is \c std::less<_Prio>.
39
  /// The \ref KaryHeap "K-ary heap" is a generalization of the
40
  /// \ref BinHeap "binary heap" structure, its nodes have at most
41
  /// \c K children, instead of two.
42
  /// \ref BinHeap and \ref FouraryHeap are specialized implementations
43
  /// of this structure for <tt>K=2</tt> and <tt>K=4</tt>, respectively.
48 44
  ///
49
  ///\sa FibHeap
50
  ///\sa Dijkstra
51
  ///\author Dorian Batha
45
  /// \tparam PR Type of the priorities of the items.
46
  /// \tparam IM A read-writable item map with \c int values, used
47
  /// internally to handle the cross references.
48
  /// \tparam CMP A functor class for comparing the priorities.
49
  /// The default is \c std::less<PR>.
50
  ///
51
  ///\sa BinHeap
52
  ///\sa FouraryHeap
53
#ifdef DOXYGEN
54
  template <typename PR, typename IM, typename CMP>
55
#else
56
  template <typename PR, typename IM, typename CMP = std::less<PR> >
57
#endif
58
  class KaryHeap {
59
  public:
60
    /// Type of the item-int map.
61
    typedef IM ItemIntMap;
62
    /// Type of the priorities.
63
    typedef PR Prio;
64
    /// Type of the items stored in the heap.
65
    typedef typename ItemIntMap::Key Item;
66
    /// Type of the item-priority pairs.
67
    typedef std::pair<Item,Prio> Pair;
68
    /// Functor type for comparing the priorities.
69
    typedef CMP Compare;
52 70

	
53
  template <typename _Prio, typename _ItemIntMap,
54
            typename _Compare = std::less<_Prio> >
55

	
56
  class KaryHeap {
57

	
58
  public:
59
    ///\e
60
    typedef _ItemIntMap ItemIntMap;
61
    ///\e
62
    typedef _Prio Prio;
63
    ///\e
64
    typedef typename ItemIntMap::Key Item;
65
    ///\e
66
    typedef std::pair<Item,Prio> Pair;
67
    ///\e
68
    typedef _Compare Compare;
69
    ///\e
70

	
71
    /// \brief Type to represent the items states.
71
    /// \brief Type to represent the states of the items.
72 72
    ///
73
    /// Each Item element have a state associated to it. It may be "in heap",
74
    /// "pre heap" or "post heap". The latter two are indifferent from the
73
    /// Each item has a state associated to it. It can be "in heap",
74
    /// "pre-heap" or "post-heap". The latter two are indifferent from the
75 75
    /// heap's point of view, but may be useful to the user.
76 76
    ///
77
    /// The ItemIntMap \e should be initialized in such way that it maps
78
    /// PRE_HEAP (-1) to any element to be put in the heap...
77
    /// The item-int map must be initialized in such way that it assigns
78
    /// \c PRE_HEAP (<tt>-1</tt>) to any element to be put in the heap.
79 79
    enum State {
80
      IN_HEAP = 0,
81
      PRE_HEAP = -1,
82
      POST_HEAP = -2
80
      IN_HEAP = 0,    ///< = 0.
81
      PRE_HEAP = -1,  ///< = -1.
82
      POST_HEAP = -2  ///< = -2.
83 83
    };
84 84

	
85 85
  private:
86
    std::vector<Pair> data;
87
    Compare comp;
88
    ItemIntMap &iim;
89
    int K;
86
    std::vector<Pair> _data;
87
    Compare _comp;
88
    ItemIntMap &_iim;
89
    int _K;
90 90

	
91 91
  public:
92
    /// \brief The constructor.
92
    /// \brief Constructor.
93 93
    ///
94
    /// The constructor.
95
    /// \param _iim should be given to the constructor, since it is used
96
    /// internally to handle the cross references. The value of the map
97
    /// should be PRE_HEAP (-1) for each element.
98
    explicit KaryHeap(ItemIntMap &_iim, const int &_K=32) : iim(_iim), K(_K) {}
94
    /// Constructor.
95
    /// \param map A map that assigns \c int values to the items.
96
    /// It is used internally to handle the cross references.
97
    /// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
98
    explicit KaryHeap(ItemIntMap &map, int K=32) : _iim(map), _K(K) {}
99 99

	
100
    /// \brief The constructor.
100
    /// \brief Constructor.
101 101
    ///
102
    /// The constructor.
103
    /// \param _iim should be given to the constructor, since it is used
104
    /// internally to handle the cross references. The value of the map
105
    /// should be PRE_HEAP (-1) for each element.
102
    /// Constructor.
103
    /// \param map A map that assigns \c int values to the items.
104
    /// It is used internally to handle the cross references.
105
    /// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
106
    /// \param comp The function object used for comparing the priorities.
107
    KaryHeap(ItemIntMap &map, const Compare &comp, int K=32)
108
      : _iim(map), _comp(comp), _K(K) {}
109

	
110
    /// \brief The number of items stored in the heap.
106 111
    ///
107
    /// \param _comp The comparator function object.
108
    KaryHeap(ItemIntMap &_iim, const Compare &_comp, const int &_K=32)
109
      : iim(_iim), comp(_comp), K(_K) {}
112
    /// This function returns the number of items stored in the heap.
113
    int size() const { return _data.size(); }
110 114

	
115
    /// \brief Check if the heap is empty.
116
    ///
117
    /// This function returns \c true if the heap is empty.
118
    bool empty() const { return _data.empty(); }
111 119

	
112
    /// The number of items stored in the heap.
120
    /// \brief Make the heap empty.
113 121
    ///
114
    /// \brief Returns the number of items stored in the heap.
115
    int size() const { return data.size(); }
116

	
117
    /// \brief Checks if the heap stores no items.
118
    ///
119
    /// Returns \c true if and only if the heap stores no items.
120
    bool empty() const { return data.empty(); }
121

	
122
    /// \brief Make empty this heap.
123
    ///
124
    /// Make empty this heap. It does not change the cross reference map.
125
    /// If you want to reuse what is not surely empty you should first clear
126
    /// the heap and after that you should set the cross reference map for
127
    /// each item to \c PRE_HEAP.
128
    void clear() { data.clear(); }
122
    /// This functon makes the heap empty.
123
    /// It does not change the cross reference map. If you want to reuse
124
    /// a heap that is not surely empty, you should first clear it and
125
    /// then you should set the cross reference map to \c PRE_HEAP
126
    /// for each item.
127
    void clear() { _data.clear(); }
129 128

	
130 129
  private:
131
    int parent(int i) { return (i-1)/K; }
132
    int first_child(int i) { return K*i+1; }
130
    int parent(int i) { return (i-1)/_K; }
131
    int firstChild(int i) { return _K*i+1; }
133 132

	
134 133
    bool less(const Pair &p1, const Pair &p2) const {
135
      return comp(p1.second, p2.second);
134
      return _comp(p1.second, p2.second);
136 135
    }
137 136

	
138
    int find_min(const int child, const int length) {
137
    int findMin(const int child, const int length) {
139 138
      int min=child, i=1;
140
      while( i<K && child+i<length ) {
141
        if( less(data[child+i], data[min]) )
139
      while( i<_K && child+i<length ) {
140
        if( less(_data[child+i], _data[min]) )
142 141
          min=child+i;
143 142
        ++i;
144 143
      }
145 144
      return min;
146 145
    }
147 146

	
148
    void bubble_up(int hole, Pair p) {
147
    void bubbleUp(int hole, Pair p) {
149 148
      int par = parent(hole);
150
      while( hole>0 && less(p,data[par]) ) {
151
        move(data[par],hole);
149
      while( hole>0 && less(p,_data[par]) ) {
150
        move(_data[par],hole);
152 151
        hole = par;
153 152
        par = parent(hole);
154 153
      }
155 154
      move(p, hole);
156 155
    }
157 156

	
158
    void bubble_down(int hole, Pair p, int length) {
157
    void bubbleDown(int hole, Pair p, int length) {
159 158
      if( length>1 ) {
160
        int child = first_child(hole);
159
        int child = firstChild(hole);
161 160
        while( child<length ) {
162
          child = find_min(child, length);
163
          if( !less(data[child], p) )
161
          child = findMin(child, length);
162
          if( !less(_data[child], p) )
164 163
            goto ok;
165
          move(data[child], hole);
164
          move(_data[child], hole);
166 165
          hole = child;
167
          child = first_child(hole);
166
          child = firstChild(hole);
168 167
        }
169 168
      }
170 169
    ok:
171 170
      move(p, hole);
172 171
    }
173 172

	
174 173
    void move(const Pair &p, int i) {
175
      data[i] = p;
176
      iim.set(p.first, i);
174
      _data[i] = p;
175
      _iim.set(p.first, i);
177 176
    }
178 177

	
179 178
  public:
180 179
    /// \brief Insert a pair of item and priority into the heap.
181 180
    ///
182
    /// Adds \c p.first to the heap with priority \c p.second.
181
    /// This function inserts \c p.first to the heap with priority
182
    /// \c p.second.
183 183
    /// \param p The pair to insert.
184
    /// \pre \c p.first must not be stored in the heap.
184 185
    void push(const Pair &p) {
185
      int n = data.size();
186
      data.resize(n+1);
187
      bubble_up(n, p);
186
      int n = _data.size();
187
      _data.resize(n+1);
188
      bubbleUp(n, p);
188 189
    }
189 190

	
190
    /// \brief Insert an item into the heap with the given heap.
191
    /// \brief Insert an item into the heap with the given priority.
191 192
    ///
192
    /// Adds \c i to the heap with priority \c p.
193
    /// This function inserts the given item into the heap with the
194
    /// given priority.
193 195
    /// \param i The item to insert.
194 196
    /// \param p The priority of the item.
197
    /// \pre \e i must not be stored in the heap.
195 198
    void push(const Item &i, const Prio &p) { push(Pair(i,p)); }
196 199

	
197
    /// \brief Returns the item with minimum priority relative to \c Compare.
200
    /// \brief Return the item having minimum priority.
198 201
    ///
199
    /// This method returns the item with minimum priority relative to \c
200
    /// Compare.
201
    /// \pre The heap must be nonempty.
202
    Item top() const { return data[0].first; }
202
    /// This function returns the item having minimum priority.
203
    /// \pre The heap must be non-empty.
204
    Item top() const { return _data[0].first; }
203 205

	
204
    /// \brief Returns the minimum priority relative to \c Compare.
206
    /// \brief The minimum priority.
205 207
    ///
206
    /// It returns the minimum priority relative to \c Compare.
207
    /// \pre The heap must be nonempty.
208
    Prio prio() const { return data[0].second; }
208
    /// This function returns the minimum priority.
209
    /// \pre The heap must be non-empty.
210
    Prio prio() const { return _data[0].second; }
209 211

	
210
    /// \brief Deletes the item with minimum priority relative to \c Compare.
212
    /// \brief Remove the item having minimum priority.
211 213
    ///
212
    /// This method deletes the item with minimum priority relative to \c
213
    /// Compare from the heap.
214
    /// This function removes the item having minimum priority.
214 215
    /// \pre The heap must be non-empty.
215 216
    void pop() {
216
      int n = data.size()-1;
217
      iim.set(data[0].first, POST_HEAP);
218
      if (n>0) bubble_down(0, data[n], n);
219
      data.pop_back();
217
      int n = _data.size()-1;
218
      _iim.set(_data[0].first, POST_HEAP);
219
      if (n>0) bubbleDown(0, _data[n], n);
220
      _data.pop_back();
220 221
    }
221 222

	
222
    /// \brief Deletes \c i from the heap.
223
    /// \brief Remove the given item from the heap.
223 224
    ///
224
    /// This method deletes item \c i from the heap.
225
    /// \param i The item to erase.
226
    /// \pre The item should be in the heap.
225
    /// This function removes the given item from the heap if it is
226
    /// already stored.
227
    /// \param i The item to delete.
228
    /// \pre \e i must be in the heap.
227 229
    void erase(const Item &i) {
228
      int h = iim[i];
229
      int n = data.size()-1;
230
      iim.set(data[h].first, POST_HEAP);
230
      int h = _iim[i];
231
      int n = _data.size()-1;
232
      _iim.set(_data[h].first, POST_HEAP);
231 233
      if( h<n ) {
232
        if( less(data[parent(h)], data[n]) )
233
          bubble_down(h, data[n], n);
234
        if( less(_data[parent(h)], _data[n]) )
235
          bubbleDown(h, _data[n], n);
234 236
        else
235
          bubble_up(h, data[n]);
237
          bubbleUp(h, _data[n]);
236 238
      }
237
      data.pop_back();
239
      _data.pop_back();
238 240
    }
239 241

	
240

	
241
    /// \brief Returns the priority of \c i.
242
    /// \brief The priority of the given item.
242 243
    ///
243
    /// This function returns the priority of item \c i.
244
    /// \pre \c i must be in the heap.
244
    /// This function returns the priority of the given item.
245 245
    /// \param i The item.
246
    /// \pre \e i must be in the heap.
246 247
    Prio operator[](const Item &i) const {
247
      int idx = iim[i];
248
      return data[idx].second;
248
      int idx = _iim[i];
249
      return _data[idx].second;
249 250
    }
250 251

	
251
    /// \brief \c i gets to the heap with priority \c p independently
252
    /// if \c i was already there.
252
    /// \brief Set the priority of an item or insert it, if it is
253
    /// not stored in the heap.
253 254
    ///
254
    /// This method calls \ref push(\c i, \c p) if \c i is not stored
255
    /// in the heap and sets the priority of \c i to \c p otherwise.
255
    /// This method sets the priority of the given item if it is
256
    /// already stored in the heap. Otherwise it inserts the given
257
    /// item into the heap with the given priority.
256 258
    /// \param i The item.
257 259
    /// \param p The priority.
258 260
    void set(const Item &i, const Prio &p) {
259
      int idx = iim[i];
261
      int idx = _iim[i];
260 262
      if( idx<0 )
261 263
        push(i,p);
262
      else if( comp(p, data[idx].second) )
263
        bubble_up(idx, Pair(i,p));
264
      else if( _comp(p, _data[idx].second) )
265
        bubbleUp(idx, Pair(i,p));
264 266
      else
265
        bubble_down(idx, Pair(i,p), data.size());
267
        bubbleDown(idx, Pair(i,p), _data.size());
266 268
    }
267 269

	
268
    /// \brief Decreases the priority of \c i to \c p.
270
    /// \brief Decrease the priority of an item to the given value.
269 271
    ///
270
    /// This method decreases the priority of item \c i to \c p.
271
    /// \pre \c i must be stored in the heap with priority at least \c
272
    /// p relative to \c Compare.
272
    /// This function decreases the priority of an item to the given value.
273 273
    /// \param i The item.
274 274
    /// \param p The priority.
275
    /// \pre \e i must be stored in the heap with priority at least \e p.
275 276
    void decrease(const Item &i, const Prio &p) {
276
      int idx = iim[i];
277
      bubble_up(idx, Pair(i,p));
277
      int idx = _iim[i];
278
      bubbleUp(idx, Pair(i,p));
278 279
    }
279 280

	
280
    /// \brief Increases the priority of \c i to \c p.
281
    /// \brief Increase the priority of an item to the given value.
281 282
    ///
282
    /// This method sets the priority of item \c i to \c p.
283
    /// \pre \c i must be stored in the heap with priority at most \c
284
    /// p relative to \c Compare.
283
    /// This function increases the priority of an item to the given value.
285 284
    /// \param i The item.
286 285
    /// \param p The priority.
286
    /// \pre \e i must be stored in the heap with priority at most \e p.
287 287
    void increase(const Item &i, const Prio &p) {
288
      int idx = iim[i];
289
      bubble_down(idx, Pair(i,p), data.size());
288
      int idx = _iim[i];
289
      bubbleDown(idx, Pair(i,p), _data.size());
290 290
    }
291 291

	
292
    /// \brief Returns if \c item is in, has already been in, or has
293
    /// never been in the heap.
292
    /// \brief Return the state of an item.
294 293
    ///
295
    /// This method returns PRE_HEAP if \c item has never been in the
296
    /// heap, IN_HEAP if it is in the heap at the moment, and POST_HEAP
297
    /// otherwise. In the latter case it is possible that \c item will
298
    /// get back to the heap again.
294
    /// This method returns \c PRE_HEAP if the given item has never
295
    /// been in the heap, \c IN_HEAP if it is in the heap at the moment,
296
    /// and \c POST_HEAP otherwise.
297
    /// In the latter case it is possible that the item will get back
298
    /// to the heap again.
299 299
    /// \param i The item.
300 300
    State state(const Item &i) const {
301
      int s = iim[i];
301
      int s = _iim[i];
302 302
      if (s>=0) s=0;
303 303
      return State(s);
304 304
    }
305 305

	
306
    /// \brief Sets the state of the \c item in the heap.
306
    /// \brief Set the state of an item in the heap.
307 307
    ///
308
    /// Sets the state of the \c item in the heap. It can be used to
309
    /// manually clear the heap when it is important to achive the
310
    /// better time complexity.
308
    /// This function sets the state of the given item in the heap.
309
    /// It can be used to manually clear the heap when it is important
310
    /// to achive better time complexity.
311 311
    /// \param i The item.
312 312
    /// \param st The state. It should not be \c IN_HEAP.
313 313
    void state(const Item& i, State st) {
314 314
      switch (st) {
315
      case POST_HEAP:
316
      case PRE_HEAP:
317
        if (state(i) == IN_HEAP) erase(i);
318
        iim[i] = st;
319
        break;
320
      case IN_HEAP:
321
        break;
315
        case POST_HEAP:
316
        case PRE_HEAP:
317
          if (state(i) == IN_HEAP) erase(i);
318
          _iim[i] = st;
319
          break;
320
        case IN_HEAP:
321
          break;
322 322
      }
323 323
    }
324 324

	
325
    /// \brief Replaces an item in the heap.
325
    /// \brief Replace an item in the heap.
326 326
    ///
327
    /// The \c i item is replaced with \c j item. The \c i item should
328
    /// be in the heap, while the \c j should be out of the heap. The
329
    /// \c i item will out of the heap and \c j will be in the heap
330
    /// with the same prioriority as prevoiusly the \c i item.
327
    /// This function replaces item \c i with item \c j.
328
    /// Item \c i must be in the heap, while \c j must be out of the heap.
329
    /// After calling this method, item \c i will be out of the
330
    /// heap and \c j will be in the heap with the same prioriority
331
    /// as item \c i had before.
331 332
    void replace(const Item& i, const Item& j) {
332
      int idx=iim[i];
333
      iim.set(i, iim[j]);
334
      iim.set(j, idx);
335
      data[idx].first=j;
333
      int idx=_iim[i];
334
      _iim.set(i, _iim[j]);
335
      _iim.set(j, idx);
336
      _data[idx].first=j;
336 337
    }
337 338

	
338 339
  }; // class KaryHeap
339 340

	
340 341
} // namespace lemon
341 342

	
342 343
#endif // LEMON_KARY_HEAP_H
Ignore white space 6 line context
1
/* -*- C++ -*-
1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 2
 *
3
 * This file is a part of LEMON, a generic C++ optimization library
3
 * This file is a part of LEMON, a generic C++ optimization library.
4 4
 *
5
 * Copyright (C) 2003-2008
5
 * Copyright (C) 2003-2009
6 6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 8
 *
9 9
 * Permission to use, modify and distribute this software is granted
10 10
 * provided that this copyright notice appears in all copies. For
11 11
 * precise terms see the accompanying LICENSE file.
12 12
 *
13 13
 * This software is provided "AS IS" with no warranty of any kind,
14 14
 * express or implied, and with no claim as to its suitability for any
15 15
 * purpose.
16 16
 *
17 17
 */
18 18

	
19 19
#ifndef LEMON_PAIRING_HEAP_H
20 20
#define LEMON_PAIRING_HEAP_H
21 21

	
22 22
///\file
23
///\ingroup auxdat
24
///\brief Pairing Heap implementation.
23
///\ingroup heaps
24
///\brief Pairing heap implementation.
25 25

	
26 26
#include <vector>
27
#include <utility>
27 28
#include <functional>
28 29
#include <lemon/math.h>
29 30

	
30 31
namespace lemon {
31 32

	
32
  /// \ingroup auxdat
33
  /// \ingroup heaps
33 34
  ///
34 35
  ///\brief Pairing Heap.
35 36
  ///
36
  ///This class implements the \e Pairing \e heap data structure. A \e heap
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
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.
37
  /// This class implements the \e pairing \e heap data structure.
38
  /// It fully conforms to the \ref concepts::Heap "heap concept".
41 39
  ///
42
  ///The methods \ref increase and \ref erase are not efficient in a Pairing
43
  ///heap. In case of many calls to these operations, it is better to use a
44
  ///\ref BinHeap "binary heap".
40
  /// The methods \ref increase() and \ref erase() are not efficient
41
  /// in a pairing heap. In case of many calls of these operations,
42
  /// it is better to use other heap structure, e.g. \ref BinHeap
43
  /// "binary heap".
45 44
  ///
46
  ///\param _Prio Type of the priority of the items.
47
  ///\param _ItemIntMap A read and writable Item int map, used internally
48
  ///to handle the cross references.
49
  ///\param _Compare A class for the ordering of the priorities. The
50
  ///default is \c std::less<_Prio>.
51
  ///
52
  ///\sa BinHeap
53
  ///\sa Dijkstra
54
  ///\author Dorian Batha
55

	
45
  /// \tparam PR Type of the priorities of the items.
46
  /// \tparam IM A read-writable item map with \c int values, used
47
  /// internally to handle the cross references.
48
  /// \tparam CMP A functor class for comparing the priorities.
49
  /// The default is \c std::less<PR>.
56 50
#ifdef DOXYGEN
57
  template <typename _Prio,
58
            typename _ItemIntMap,
59
            typename _Compare>
51
  template <typename PR, typename IM, typename CMP>
60 52
#else
61
  template <typename _Prio,
62
            typename _ItemIntMap,
63
            typename _Compare = std::less<_Prio> >
53
  template <typename PR, typename IM, typename CMP = std::less<PR> >
64 54
#endif
65 55
  class PairingHeap {
66 56
  public:
67
    typedef _ItemIntMap ItemIntMap;
68
    typedef _Prio Prio;
57
    /// Type of the item-int map.
58
    typedef IM ItemIntMap;
59
    /// Type of the priorities.
60
    typedef PR Prio;
61
    /// Type of the items stored in the heap.
69 62
    typedef typename ItemIntMap::Key Item;
70
    typedef std::pair<Item,Prio> Pair;
71
    typedef _Compare Compare;
63
    /// Functor type for comparing the priorities.
64
    typedef CMP Compare;
65

	
66
    /// \brief Type to represent the states of the items.
67
    ///
68
    /// Each item has a state associated to it. It can be "in heap",
69
    /// "pre-heap" or "post-heap". The latter two are indifferent from the
70
    /// heap's point of view, but may be useful to the user.
71
    ///
72
    /// The item-int map must be initialized in such way that it assigns
73
    /// \c PRE_HEAP (<tt>-1</tt>) to any element to be put in the heap.
74
    enum State {
75
      IN_HEAP = 0,    ///< = 0.
76
      PRE_HEAP = -1,  ///< = -1.
77
      POST_HEAP = -2  ///< = -2.
78
    };
72 79

	
73 80
  private:
74 81
    class store;
75 82

	
76
    std::vector<store> container;
77
    int minimum;
78
    ItemIntMap &iimap;
79
    Compare comp;
80
    int num_items;
83
    std::vector<store> _data;
84
    int _min;
85
    ItemIntMap &_iim;
86
    Compare _comp;
87
    int _num_items;
81 88

	
82 89
  public:
83
    ///Status of the nodes
84
    enum State {
85
      ///The node is in the heap
86
      IN_HEAP = 0,
87
      ///The node has never been in the heap
88
      PRE_HEAP = -1,
89
      ///The node was in the heap but it got out of it
90
      POST_HEAP = -2
91
    };
90
    /// \brief Constructor.
91
    ///
92
    /// Constructor.
93
    /// \param map A map that assigns \c int values to the items.
94
    /// It is used internally to handle the cross references.
95
    /// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
96
    explicit PairingHeap(ItemIntMap &map)
97
      : _min(0), _iim(map), _num_items(0) {}
92 98

	
93
    /// \brief The constructor
99
    /// \brief Constructor.
94 100
    ///
95
    /// \c _iimap should be given to the constructor, since it is
96
    ///   used internally to handle the cross references.
97
    explicit PairingHeap(ItemIntMap &_iimap)
98
      : minimum(0), iimap(_iimap), num_items(0) {}
99

	
100
    /// \brief The constructor
101
    ///
102
    /// \c _iimap should be given to the constructor, since it is used
103
    /// internally to handle the cross references. \c _comp is an
104
    /// object for ordering of the priorities.
105
    PairingHeap(ItemIntMap &_iimap, const Compare &_comp)
106
      : minimum(0), iimap(_iimap), comp(_comp), num_items(0) {}
101
    /// Constructor.
102
    /// \param map A map that assigns \c int values to the items.
103
    /// It is used internally to handle the cross references.
104
    /// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
105
    /// \param comp The function object used for comparing the priorities.
106
    PairingHeap(ItemIntMap &map, const Compare &comp)
107
      : _min(0), _iim(map), _comp(comp), _num_items(0) {}
107 108

	
108 109
    /// \brief The number of items stored in the heap.
109 110
    ///
110
    /// Returns the number of items stored in the heap.
111
    int size() const { return num_items; }
111
    /// This function returns the number of items stored in the heap.
112
    int size() const { return _num_items; }
112 113

	
113
    /// \brief Checks if the heap stores no items.
114
    /// \brief Check if the heap is empty.
114 115
    ///
115
    ///   Returns \c true if and only if the heap stores no items.
116
    bool empty() const { return num_items==0; }
116
    /// This function returns \c true if the heap is empty.
117
    bool empty() const { return _num_items==0; }
117 118

	
118
    /// \brief Make empty this heap.
119
    /// \brief Make the heap empty.
119 120
    ///
120
    /// Make empty this heap. It does not change the cross reference
121
    /// map.  If you want to reuse a heap what is not surely empty you
122
    /// should first clear the heap and after that you should set the
123
    /// cross reference map for each item to \c PRE_HEAP.
121
    /// This functon makes the heap empty.
122
    /// It does not change the cross reference map. If you want to reuse
123
    /// a heap that is not surely empty, you should first clear it and
124
    /// then you should set the cross reference map to \c PRE_HEAP
125
    /// for each item.
124 126
    void clear() {
125
      container.clear();
126
      minimum = 0;
127
      num_items = 0;
127
      _data.clear();
128
      _min = 0;
129
      _num_items = 0;
128 130
    }
129 131

	
130
    /// \brief \c item gets to the heap with priority \c value independently
131
    /// if \c item was already there.
132
    /// \brief Set the priority of an item or insert it, if it is
133
    /// not stored in the heap.
132 134
    ///
133
    /// This method calls \ref push(\c item, \c value) if \c item is not
134
    /// stored in the heap and it calls \ref decrease(\c item, \c value) or
135
    /// \ref increase(\c item, \c value) otherwise.
135
    /// This method sets the priority of the given item if it is
136
    /// already stored in the heap. Otherwise it inserts the given
137
    /// item into the heap with the given priority.
138
    /// \param item The item.
139
    /// \param value The priority.
136 140
    void set (const Item& item, const Prio& value) {
137
      int i=iimap[item];
138
      if ( i>=0 && container[i].in ) {
139
        if ( comp(value, container[i].prio) ) decrease(item, value);
140
        if ( comp(container[i].prio, value) ) increase(item, value);
141
      int i=_iim[item];
142
      if ( i>=0 && _data[i].in ) {
143
        if ( _comp(value, _data[i].prio) ) decrease(item, value);
144
        if ( _comp(_data[i].prio, value) ) increase(item, value);
141 145
      } else push(item, value);
142 146
    }
143 147

	
144
    /// \brief Adds \c item to the heap with priority \c value.
148
    /// \brief Insert an item into the heap with the given priority.
145 149
    ///
146
    /// Adds \c item to the heap with priority \c value.
147
    /// \pre \c item must not be stored in the heap.
150
    /// This function inserts the given item into the heap with the
151
    /// given priority.
152
    /// \param item The item to insert.
153
    /// \param value The priority of the item.
154
    /// \pre \e item must not be stored in the heap.
148 155
    void push (const Item& item, const Prio& value) {
149
      int i=iimap[item];
156
      int i=_iim[item];
150 157
      if( i<0 ) {
151
        int s=container.size();
152
        iimap.set(item, s);
158
        int s=_data.size();
159
        _iim.set(item, s);
153 160
        store st;
154 161
        st.name=item;
155
        container.push_back(st);
162
        _data.push_back(st);
156 163
        i=s;
157 164
      } else {
158
        container[i].parent=container[i].child=-1;
159
        container[i].left_child=false;
160
        container[i].degree=0;
161
        container[i].in=true;
165
        _data[i].parent=_data[i].child=-1;
166
        _data[i].left_child=false;
167
        _data[i].degree=0;
168
        _data[i].in=true;
162 169
      }
163 170

	
164
      container[i].prio=value;
171
      _data[i].prio=value;
165 172

	
166
      if ( num_items!=0 ) {
167
        if ( comp( value, container[minimum].prio) ) {
168
          fuse(i,minimum);
169
          minimum=i;
173
      if ( _num_items!=0 ) {
174
        if ( _comp( value, _data[_min].prio) ) {
175
          fuse(i,_min);
176
          _min=i;
170 177
        }
171
        else fuse(minimum,i);
178
        else fuse(_min,i);
172 179
      }
173
      else minimum=i;
180
      else _min=i;
174 181

	
175
      ++num_items;
182
      ++_num_items;
176 183
    }
177 184

	
178
    /// \brief Returns the item with minimum priority relative to \c Compare.
185
    /// \brief Return the item having minimum priority.
179 186
    ///
180
    /// This method returns the item with minimum priority relative to \c
181
    /// Compare.
182
    /// \pre The heap must be nonempty.
183
    Item top() const { return container[minimum].name; }
187
    /// This function returns the item having minimum priority.
188
    /// \pre The heap must be non-empty.
189
    Item top() const { return _data[_min].name; }
184 190

	
185
    /// \brief Returns the minimum priority relative to \c Compare.
191
    /// \brief The minimum priority.
186 192
    ///
187
    /// It returns the minimum priority relative to \c Compare.
188
    /// \pre The heap must be nonempty.
189
    const Prio& prio() const { return container[minimum].prio; }
193
    /// This function returns the minimum priority.
194
    /// \pre The heap must be non-empty.
195
    const Prio& prio() const { return _data[_min].prio; }
190 196

	
191
    /// \brief Returns the priority of \c item.
197
    /// \brief The priority of the given item.
192 198
    ///
193
    /// It returns the priority of \c item.
194
    /// \pre \c item must be in the heap.
199
    /// This function returns the priority of the given item.
200
    /// \param item The item.
201
    /// \pre \e item must be in the heap.
195 202
    const Prio& operator[](const Item& item) const {
196
      return container[iimap[item]].prio;
203
      return _data[_iim[item]].prio;
197 204
    }
198 205

	
199
    /// \brief Deletes the item with minimum priority relative to \c Compare.
206
    /// \brief Remove the item having minimum priority.
200 207
    ///
201
    /// This method deletes the item with minimum priority relative to \c
202
    /// Compare from the heap.
208
    /// This function removes the item having minimum priority.
203 209
    /// \pre The heap must be non-empty.
204 210
    void pop() {
205
      int TreeArray[num_items];
211
      int TreeArray[_num_items];
206 212
      int i=0, num_child=0, child_right = 0;
207
      container[minimum].in=false;
213
      _data[_min].in=false;
208 214

	
209
      if( -1!=container[minimum].child ) {
210
        i=container[minimum].child;
215
      if( -1!=_data[_min].child ) {
216
        i=_data[_min].child;
211 217
        TreeArray[num_child] = i;
212
        container[i].parent = -1;
213
        container[minimum].child = -1;
218
        _data[i].parent = -1;
219
        _data[_min].child = -1;
214 220

	
215 221
        ++num_child;
216 222
        int ch=-1;
217
        while( container[i].child!=-1 ) {
218
          ch=container[i].child;
219
          if( container[ch].left_child && i==container[ch].parent ) {
223
        while( _data[i].child!=-1 ) {
224
          ch=_data[i].child;
225
          if( _data[ch].left_child && i==_data[ch].parent ) {
220 226
            i=ch;
221 227
            //break;
222 228
          } else {
223
            if( container[ch].left_child ) {
224
              child_right=container[ch].parent;
225
              container[ch].parent = i;
226
              --container[i].degree;
229
            if( _data[ch].left_child ) {
230
              child_right=_data[ch].parent;
231
              _data[ch].parent = i;
232
              --_data[i].degree;
227 233
            }
228 234
            else {
229 235
              child_right=ch;
230
              container[i].child=-1;
231
              container[i].degree=0;
236
              _data[i].child=-1;
237
              _data[i].degree=0;
232 238
            }
233
            container[child_right].parent = -1;
239
            _data[child_right].parent = -1;
234 240
            TreeArray[num_child] = child_right;
235 241
            i = child_right;
236 242
            ++num_child;
237 243
          }
238 244
        }
239 245

	
240 246
        int other;
241 247
        for( i=0; i<num_child-1; i+=2 ) {
242
          if ( !comp(container[TreeArray[i]].prio,
243
                     container[TreeArray[i+1]].prio) ) {
248
          if ( !_comp(_data[TreeArray[i]].prio,
249
                     _data[TreeArray[i+1]].prio) ) {
244 250
            other=TreeArray[i];
245 251
            TreeArray[i]=TreeArray[i+1];
246 252
            TreeArray[i+1]=other;
247 253
          }
248 254
          fuse( TreeArray[i], TreeArray[i+1] );
249 255
        }
250 256

	
251 257
        i = (0==(num_child % 2)) ? num_child-2 : num_child-1;
252 258
        while(i>=2) {
253
          if ( comp(container[TreeArray[i]].prio,
254
                    container[TreeArray[i-2]].prio) ) {
259
          if ( _comp(_data[TreeArray[i]].prio,
260
                    _data[TreeArray[i-2]].prio) ) {
255 261
            other=TreeArray[i];
256 262
            TreeArray[i]=TreeArray[i-2];
257 263
            TreeArray[i-2]=other;
258 264
          }
259 265
          fuse( TreeArray[i-2], TreeArray[i] );
260 266
          i-=2;
261 267
        }
262
        minimum = TreeArray[0];
268
        _min = TreeArray[0];
263 269
      }
264 270

	
265 271
      if ( 0==num_child ) {
266
        minimum = container[minimum].child;
272
        _min = _data[_min].child;
267 273
      }
268 274

	
269
      if (minimum >= 0) container[minimum].left_child = false;
275
      if (_min >= 0) _data[_min].left_child = false;
270 276

	
271
      --num_items;
277
      --_num_items;
272 278
    }
273 279

	
274
    /// \brief Deletes \c item from the heap.
280
    /// \brief Remove the given item from the heap.
275 281
    ///
276
    /// This method deletes \c item from the heap, if \c item was already
277
    /// stored in the heap. It is quite inefficient in Pairing heaps.
282
    /// This function removes the given item from the heap if it is
283
    /// already stored.
284
    /// \param item The item to delete.
285
    /// \pre \e item must be in the heap.
278 286
    void erase (const Item& item) {
279
      int i=iimap[item];
280
      if ( i>=0 && container[i].in ) {
281
        decrease( item, container[minimum].prio-1 );
287
      int i=_iim[item];
288
      if ( i>=0 && _data[i].in ) {
289
        decrease( item, _data[_min].prio-1 );
282 290
        pop();
283 291
      }
284 292
    }
285 293

	
286
    /// \brief Decreases the priority of \c item to \c value.
294
    /// \brief Decrease the priority of an item to the given value.
287 295
    ///
288
    /// This method decreases the priority of \c item to \c value.
289
    /// \pre \c item must be stored in the heap with priority at least \c
290
    ///   value relative to \c Compare.
296
    /// This function decreases the priority of an item to the given value.
297
    /// \param item The item.
298
    /// \param value The priority.
299
    /// \pre \e item must be stored in the heap with priority at least \e value.
291 300
    void decrease (Item item, const Prio& value) {
292
      int i=iimap[item];
293
      container[i].prio=value;
294
      int p=container[i].parent;
301
      int i=_iim[item];
302
      _data[i].prio=value;
303
      int p=_data[i].parent;
295 304

	
296
      if( container[i].left_child && i!=container[p].child ) {
297
        p=container[p].parent;
305
      if( _data[i].left_child && i!=_data[p].child ) {
306
        p=_data[p].parent;
298 307
      }
299 308

	
300
      if ( p!=-1 && comp(value,container[p].prio) ) {
309
      if ( p!=-1 && _comp(value,_data[p].prio) ) {
301 310
        cut(i,p);
302
        if ( comp(container[minimum].prio,value) ) {
303
          fuse(minimum,i);
311
        if ( _comp(_data[_min].prio,value) ) {
312
          fuse(_min,i);
304 313
        } else {
305
          fuse(i,minimum);
306
          minimum=i;
314
          fuse(i,_min);
315
          _min=i;
307 316
        }
308 317
      }
309 318
    }
310 319

	
311
    /// \brief Increases the priority of \c item to \c value.
320
    /// \brief Increase the priority of an item to the given value.
312 321
    ///
313
    /// This method sets the priority of \c item to \c value. Though
314
    /// there is no precondition on the priority of \c item, this
315
    /// method should be used only if it is indeed necessary to increase
316
    /// (relative to \c Compare) the priority of \c item, because this
317
    /// method is inefficient.
322
    /// This function increases the priority of an item to the given value.
323
    /// \param item The item.
324
    /// \param value The priority.
325
    /// \pre \e item must be stored in the heap with priority at most \e value.
318 326
    void increase (Item item, const Prio& value) {
319 327
      erase(item);
320 328
      push(item,value);
321 329
    }
322 330

	
323
    /// \brief Returns if \c item is in, has already been in, or has never
324
    /// been in the heap.
331
    /// \brief Return the state of an item.
325 332
    ///
326
    /// This method returns PRE_HEAP if \c item has never been in the
327
    /// heap, IN_HEAP if it is in the heap at the moment, and POST_HEAP
328
    /// otherwise. In the latter case it is possible that \c item will
329
    /// get back to the heap again.
333
    /// This method returns \c PRE_HEAP if the given item has never
334
    /// been in the heap, \c IN_HEAP if it is in the heap at the moment,
335
    /// and \c POST_HEAP otherwise.
336
    /// In the latter case it is possible that the item will get back
337
    /// to the heap again.
338
    /// \param item The item.
330 339
    State state(const Item &item) const {
331
      int i=iimap[item];
340
      int i=_iim[item];
332 341
      if( i>=0 ) {
333
        if( container[i].in ) i=0;
342
        if( _data[i].in ) i=0;
334 343
        else i=-2;
335 344
      }
336 345
      return State(i);
337 346
    }
338 347

	
339
    /// \brief Sets the state of the \c item in the heap.
348
    /// \brief Set the state of an item in the heap.
340 349
    ///
341
    /// Sets the state of the \c item in the heap. It can be used to
342
    /// manually clear the heap when it is important to achive the
343
    /// better time complexity.
350
    /// This function sets the state of the given item in the heap.
351
    /// It can be used to manually clear the heap when it is important
352
    /// to achive better time complexity.
344 353
    /// \param i The item.
345 354
    /// \param st The state. It should not be \c IN_HEAP.
346 355
    void state(const Item& i, State st) {
347 356
      switch (st) {
348 357
      case POST_HEAP:
349 358
      case PRE_HEAP:
350 359
        if (state(i) == IN_HEAP) erase(i);
351
        iimap[i]=st;
360
        _iim[i]=st;
352 361
        break;
353 362
      case IN_HEAP:
354 363
        break;
355 364
      }
356 365
    }
357 366

	
358 367
  private:
359 368

	
360 369
    void cut(int a, int b) {
361 370
      int child_a;
362
      switch (container[a].degree) {
371
      switch (_data[a].degree) {
363 372
        case 2:
364
          child_a = container[container[a].child].parent;
365
          if( container[a].left_child ) {
366
            container[child_a].left_child=true;
367
            container[b].child=child_a;
368
            container[child_a].parent=container[a].parent;
373
          child_a = _data[_data[a].child].parent;
374
          if( _data[a].left_child ) {
375
            _data[child_a].left_child=true;
376
            _data[b].child=child_a;
377
            _data[child_a].parent=_data[a].parent;
369 378
          }
370 379
          else {
371
            container[child_a].left_child=false;
372
            container[child_a].parent=b;
373
            if( a!=container[b].child )
374
              container[container[b].child].parent=child_a;
380
            _data[child_a].left_child=false;
381
            _data[child_a].parent=b;
382
            if( a!=_data[b].child )
383
              _data[_data[b].child].parent=child_a;
375 384
            else
376
              container[b].child=child_a;
385
              _data[b].child=child_a;
377 386
          }
378
          --container[a].degree;
379
          container[container[a].child].parent=a;
387
          --_data[a].degree;
388
          _data[_data[a].child].parent=a;
380 389
          break;
381 390

	
382 391
        case 1:
383
          child_a = container[a].child;
384
          if( !container[child_a].left_child ) {
385
            --container[a].degree;
386
            if( container[a].left_child ) {
387
              container[child_a].left_child=true;
388
              container[child_a].parent=container[a].parent;
389
              container[b].child=child_a;
392
          child_a = _data[a].child;
393
          if( !_data[child_a].left_child ) {
394
            --_data[a].degree;
395
            if( _data[a].left_child ) {
396
              _data[child_a].left_child=true;
397
              _data[child_a].parent=_data[a].parent;
398
              _data[b].child=child_a;
390 399
            }
391 400
            else {
392
              container[child_a].left_child=false;
393
              container[child_a].parent=b;
394
              if( a!=container[b].child )
395
                container[container[b].child].parent=child_a;
401
              _data[child_a].left_child=false;
402
              _data[child_a].parent=b;
403
              if( a!=_data[b].child )
404
                _data[_data[b].child].parent=child_a;
396 405
              else
397
                container[b].child=child_a;
406
                _data[b].child=child_a;
398 407
            }
399
            container[a].child=-1;
408
            _data[a].child=-1;
400 409
          }
401 410
          else {
402
            --container[b].degree;
403
            if( container[a].left_child ) {
404
              container[b].child =
405
                (1==container[b].degree) ? container[a].parent : -1;
411
            --_data[b].degree;
412
            if( _data[a].left_child ) {
413
              _data[b].child =
414
                (1==_data[b].degree) ? _data[a].parent : -1;
406 415
            } else {
407
              if (1==container[b].degree)
408
                container[container[b].child].parent=b;
416
              if (1==_data[b].degree)
417
                _data[_data[b].child].parent=b;
409 418
              else
410
                container[b].child=-1;
419
                _data[b].child=-1;
411 420
            }
412 421
          }
413 422
          break;
414 423

	
415 424
        case 0:
416
          --container[b].degree;
417
          if( container[a].left_child ) {
418
            container[b].child =
419
              (0!=container[b].degree) ? container[a].parent : -1;
425
          --_data[b].degree;
426
          if( _data[a].left_child ) {
427
            _data[b].child =
428
              (0!=_data[b].degree) ? _data[a].parent : -1;
420 429
          } else {
421
            if( 0!=container[b].degree )
422
              container[container[b].child].parent=b;
430
            if( 0!=_data[b].degree )
431
              _data[_data[b].child].parent=b;
423 432
            else
424
              container[b].child=-1;
433
              _data[b].child=-1;
425 434
          }
426 435
          break;
427 436
      }
428
      container[a].parent=-1;
429
      container[a].left_child=false;
437
      _data[a].parent=-1;
438
      _data[a].left_child=false;
430 439
    }
431 440

	
432 441
    void fuse(int a, int b) {
433
      int child_a = container[a].child;
434
      int child_b = container[b].child;
435
      container[a].child=b;
436
      container[b].parent=a;
437
      container[b].left_child=true;
442
      int child_a = _data[a].child;
443
      int child_b = _data[b].child;
444
      _data[a].child=b;
445
      _data[b].parent=a;
446
      _data[b].left_child=true;
438 447

	
439 448
      if( -1!=child_a ) {
440
        container[b].child=child_a;
441
        container[child_a].parent=b;
442
        container[child_a].left_child=false;
443
        ++container[b].degree;
449
        _data[b].child=child_a;
450
        _data[child_a].parent=b;
451
        _data[child_a].left_child=false;
452
        ++_data[b].degree;
444 453

	
445 454
        if( -1!=child_b ) {
446
           container[b].child=child_b;
447
           container[child_b].parent=child_a;
455
           _data[b].child=child_b;
456
           _data[child_b].parent=child_a;
448 457
        }
449 458
      }
450
      else { ++container[a].degree; }
459
      else { ++_data[a].degree; }
451 460
    }
452 461

	
453 462
    class store {
454 463
      friend class PairingHeap;
455 464

	
456 465
      Item name;
457 466
      int parent;
458 467
      int child;
459 468
      bool left_child;
460 469
      int degree;
461 470
      bool in;
462 471
      Prio prio;
463 472

	
464 473
      store() : parent(-1), child(-1), left_child(false), degree(0), in(true) {}
465 474
    };
466 475
  };
467 476

	
468 477
} //namespace lemon
469 478

	
470 479
#endif //LEMON_PAIRING_HEAP_H
471 480

	
0 comments (0 inline)