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

	
19
#ifndef LEMON_BINOM_HEAP_H
20
#define LEMON_BINOM_HEAP_H
21

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

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

	
31
namespace lemon {
32

	
33
  /// \ingroup auxdat
34
  ///
35
  ///\brief Binomial Heap.
36
  ///
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.
42
  ///
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".
46
  ///
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

	
57
#ifdef DOXYGEN
58
  template <typename _Prio,
59
            typename _ItemIntMap,
60
            typename _Compare>
61
#else
62
  template <typename _Prio,
63
            typename _ItemIntMap,
64
            typename _Compare = std::less<_Prio> >
65
#endif
66
  class BinomHeap {
67
  public:
68
    typedef _ItemIntMap ItemIntMap;
69
    typedef _Prio Prio;
70
    typedef typename ItemIntMap::Key Item;
71
    typedef std::pair<Item,Prio> Pair;
72
    typedef _Compare Compare;
73

	
74
  private:
75
    class store;
76

	
77
    std::vector<store> container;
78
    int minimum, head;
79
    ItemIntMap &iimap;
80
    Compare comp;
81
    int num_items;
82

	
83
  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
    };
93

	
94
    /// \brief The constructor
95
    ///
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() {}
108

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

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

	
119
    /// \brief Make empty this heap.
120
    ///
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.
125
    void clear() {
126
      container.clear(); minimum=0; num_items=0; head=-1;
127
    }
128

	
129
    /// \brief \c item gets to the heap with priority \c value independently
130
    /// if \c item was already there.
131
    ///
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.
135
    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
      } else push(item, value);
141
    }
142

	
143
    /// \brief Adds \c item to the heap with priority \c value.
144
    ///
145
    /// Adds \c item to the heap with priority \c value.
146
    /// \pre \c item must not be stored in the heap.
147
    void push (const Item& item, const Prio& value) {
148
      int i=iimap[item];
149
      if ( i<0 ) {
150
        int s=container.size();
151
        iimap.set( item,s );
152
        store st;
153
        st.name=item;
154
        container.push_back(st);
155
        i=s;
156
      }
157
      else {
158
        container[i].parent=container[i].right_neighbor=container[i].child=-1;
159
        container[i].degree=0;
160
        container[i].in=true;
161
      }
162
      container[i].prio=value;
163

	
164
      if( 0==num_items ) { head=i; minimum=i; }
165
      else { merge(i); }
166

	
167
      minimum = find_min();
168

	
169
      ++num_items;
170
    }
171

	
172
    /// \brief Returns the item with minimum priority relative to \c Compare.
173
    ///
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; }
178

	
179
    /// \brief Returns the minimum priority relative to \c Compare.
180
    ///
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; }
184

	
185
    /// \brief Returns the priority of \c item.
186
    ///
187
    /// It returns the priority of \c item.
188
    /// \pre \c item must be in the heap.
189
    const Prio& operator[](const Item& item) const {
190
      return container[iimap[item]].prio;
191
    }
192

	
193
    /// \brief Deletes the item with minimum priority relative to \c Compare.
194
    ///
195
    /// This method deletes the item with minimum priority relative to \c
196
    /// Compare from the heap.
197
    /// \pre The heap must be non-empty.
198
    void pop() {
199
      container[minimum].in=false;
200

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

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

	
225
        merge(head_child);
226
      }
227
      minimum=find_min();
228
      --num_items;
229
    }
230

	
231
    /// \brief Deletes \c item from the heap.
232
    ///
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.
235
    void erase (const Item& item) {
236
      int i=iimap[item];
237
      if ( i >= 0 && container[i].in ) {
238
        decrease( item, container[minimum].prio-1 );
239
        pop();
240
      }
241
    }
242

	
243
    /// \brief Decreases the priority of \c item to \c value.
244
    ///
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.
248
    void decrease (Item item, const Prio& value) {
249
      int i=iimap[item];
250

	
251
      if( comp( value,container[i].prio ) ) {
252
        container[i].prio=value;
253

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

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

	
259
          // parent set for other loc_child
260
          child=container[loc].child;
261
          while( -1!=child ) {
262
            container[child].parent=p_loc;
263
            child=container[child].right_neighbor;
264
          }
265

	
266
          // parent set for other p_loc_child
267
          child=container[p_loc].child;
268
          while( -1!=child ) {
269
            container[child].parent=loc;
270
            child=container[child].right_neighbor;
271
          }
272

	
273
          child=container[p_loc].child;
274
          container[p_loc].child=container[loc].child;
275
          if( child==loc )
276
            child=p_loc;
277
          container[loc].child=child;
278

	
279
          // 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;
284
          }
285

	
286
          // left_neighb set for loc
287
          parent=container[p_loc].parent;
288
          if( -1!=parent ) child=container[parent].child;
289
          else child=head;
290

	
291
          if( child!=p_loc ) {
292
            while( container[child].right_neighbor!=p_loc )
293
              child=container[child].right_neighbor;
294
            container[child].right_neighbor=loc;
295
          }
296

	
297
          neighb=container[p_loc].right_neighbor;
298
          container[p_loc].right_neighbor=container[loc].right_neighbor;
299
          container[loc].right_neighbor=neighb;
300

	
301
          container[p_loc].parent=loc;
302
          container[loc].parent=parent;
303

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

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

	
311
          p_loc=container[loc].parent;
312
        }
313
      }
314
      if( comp(value,container[minimum].prio) ) {
315
        minimum=i;
316
      }
317
    }
318

	
319
    /// \brief Increases the priority of \c item to \c value.
320
    ///
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.
326
    void increase (Item item, const Prio& value) {
327
      erase(item);
328
      push(item, value);
329
    }
330

	
331

	
332
    /// \brief Returns if \c item is in, has already been in, or has never
333
    /// been in the heap.
334
    ///
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.
339
    State state(const Item &item) const {
340
      int i=iimap[item];
341
      if( i>=0 ) {
342
        if ( container[i].in ) i=0;
343
        else i=-2;
344
      }
345
      return State(i);
346
    }
347

	
348
    /// \brief Sets the state of the \c item in the heap.
349
    ///
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.
353
    /// \param i The item.
354
    /// \param st The state. It should not be \c IN_HEAP.
355
    void state(const Item& i, State st) {
356
      switch (st) {
357
      case POST_HEAP:
358
      case PRE_HEAP:
359
        if (state(i) == IN_HEAP) {
360
          erase(i);
361
        }
362
        iimap[i] = st;
363
        break;
364
      case IN_HEAP:
365
        break;
366
      }
367
    }
368

	
369
  private:
370
    int find_min() {
371
      int min_loc=-1, min_val;
372
      int x=head;
373
      if( x!=-1 ) {
374
        min_val=container[x].prio;
375
        min_loc=x;
376
        x=container[x].right_neighbor;
377

	
378
        while( x!=-1 ) {
379
          if( comp( container[x].prio,min_val ) ) {
380
            min_val=container[x].prio;
381
            min_loc=x;
382
          }
383
          x=container[x].right_neighbor;
384
        }
385
      }
386
      return min_loc;
387
    }
388

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

	
392
      int x=head;
393
      if( -1!=x ) {
394
        int x_prev=-1, x_next=container[x].right_neighbor;
395
        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 ) ) {
397
            x_prev=x;
398
            x=x_next;
399
          }
400
          else {
401
            if( comp(container[x].prio,container[x_next].prio) ) {
402
              container[x].right_neighbor=container[x_next].right_neighbor;
403
              fuse(x_next,x);
404
            }
405
            else {
406
              if( -1==x_prev ) { head=x_next; }
407
              else {
408
                container[x_prev].right_neighbor=x_next;
409
              }
410
              fuse(x,x_next);
411
              x=x_next;
412
            }
413
          }
414
          x_next=container[x].right_neighbor;
415
        }
416
      }
417
    }
418

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

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

	
467
    // Lacing a under b
468
    void fuse(int a, int b) {
469
      container[a].parent=b;
470
      container[a].right_neighbor=container[b].child;
471
      container[b].child=a;
472

	
473
      ++container[b].degree;
474
    }
475

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

	
481
      while( container[other].right_neighbor!=a )
482
        other=container[other].right_neighbor;
483
      container[other].right_neighbor=neighb;
484
    }
485

	
486
  private:
487

	
488
    class store {
489
      friend class BinomHeap;
490

	
491
      Item name;
492
      int parent;
493
      int right_neighbor;
494
      int child;
495
      int degree;
496
      bool in;
497
      Prio prio;
498

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

	
503
} //namespace lemon
504

	
505
#endif //LEMON_BINOM_HEAP_H
506

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

	
19
#ifndef LEMON_FOURARY_HEAP_H
20
#define LEMON_FOURARY_HEAP_H
21

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

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

	
31
namespace lemon {
32

	
33
  ///\ingroup auxdat
34
  ///
35
  ///\brief A 4ary Heap implementation.
36
  ///
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.
42
  ///
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>.
48
  ///
49
  ///\sa FibHeap
50
  ///\sa Dijkstra
51
  ///\author Dorian Batha
52

	
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.
71
    ///
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
74
    /// heap's point of view, but may be useful to the user.
75
    ///
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...
78
    enum State {
79
      IN_HEAP = 0,
80
      PRE_HEAP = -1,
81
      POST_HEAP = -2
82
    };
83

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

	
89
  public:
90
    /// \brief The constructor.
91
    ///
92
    /// The constructor.
93
    /// \param _iim should be given to the constructor, since it is used
94
    /// internally to handle the cross references. The value of the map
95
    /// should be PRE_HEAP (-1) for each element.
96
    explicit FouraryHeap(ItemIntMap &_iim) : iim(_iim) {}
97

	
98
    /// \brief The constructor.
99
    ///
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.
104
    ///
105
    /// \param _comp The comparator function object.
106
    FouraryHeap(ItemIntMap &_iim, const Compare &_comp)
107
      : iim(_iim), comp(_comp) {}
108

	
109
    /// The number of items stored in the heap.
110
    ///
111
    /// \brief Returns the number of items stored in the heap.
112
    int size() const { return data.size(); }
113

	
114
    /// \brief Checks if the heap stores no items.
115
    ///
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(); }
126

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

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

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

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

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

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

	
187
  public:
188

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

	
199
    /// \brief Insert an item into the heap with the given heap.
200
    ///
201
    /// Adds \c i to the heap with priority \c p.
202
    /// \param i The item to insert.
203
    /// \param p The priority of the item.
204
    void push(const Item &i, const Prio &p) { push(Pair(i,p)); }
205

	
206
    /// \brief Returns the item with minimum priority relative to \c Compare.
207
    ///
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; }
212

	
213
    /// \brief Returns the minimum priority relative to \c Compare.
214
    ///
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; }
218

	
219
    /// \brief Deletes the item with minimum priority relative to \c Compare.
220
    ///
221
    /// This method deletes the item with minimum priority relative to \c
222
    /// Compare from the heap.
223
    /// \pre The heap must be non-empty.
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();
229
    }
230

	
231
    /// \brief Deletes \c i from the heap.
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.
236
    void erase(const Item &i) {
237
      int h = iim[i];
238
      int n = data.size()-1;
239
      iim.set(data[h].first, POST_HEAP);
240
      if( h<n ) {
241
        if( less(data[parent(h)], data[n]) )
242
          bubble_down(h, data[n], n);
243
        else
244
          bubble_up(h, data[n]);
245
      }
246
      data.pop_back();
247
    }
248

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

	
259
    /// \brief \c i gets to the heap with priority \c p independently
260
    /// if \c i was already there.
261
    ///
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.
264
    /// \param i The item.
265
    /// \param p The priority.
266
    void set(const Item &i, const Prio &p) {
267
      int idx = iim[i];
268
      if( idx < 0 )
269
        push(i,p);
270
      else if( comp(p, data[idx].second) )
271
        bubble_up(idx, Pair(i,p));
272
      else
273
        bubble_down(idx, Pair(i,p), data.size());
274
    }
275

	
276
    /// \brief Decreases the priority of \c i to \c p.
277
    ///
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.
281
    /// \param i The item.
282
    /// \param p The priority.
283
    void decrease(const Item &i, const Prio &p) {
284
      int idx = iim[i];
285
      bubble_up(idx, Pair(i,p));
286
    }
287

	
288
    /// \brief Increases the priority of \c i to \c p.
289
    ///
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.
293
    /// \param i The item.
294
    /// \param p The priority.
295
    void increase(const Item &i, const Prio &p) {
296
      int idx = iim[i];
297
      bubble_down(idx, Pair(i,p), data.size());
298
    }
299

	
300
    /// \brief Returns if \c item is in, has already been in, or has
301
    /// never been in the heap.
302
    ///
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.
307
    /// \param i The item.
308
    State state(const Item &i) const {
309
      int s = iim[i];
310
      if (s>=0) s=0;
311
      return State(s);
312
    }
313

	
314
    /// \brief Sets the state of the \c item in the heap.
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.
319
    /// \param i The item.
320
    /// \param st The state. It should not be \c IN_HEAP.
321
    void state(const Item& i, State st) {
322
      switch (st) {
323
        case POST_HEAP:
324
        case PRE_HEAP:
325
          if (state(i) == IN_HEAP) erase(i);
326
          iim[i] = st;
327
          break;
328
        case IN_HEAP:
329
          break;
330
      }
331
    }
332

	
333
    /// \brief Replaces an item in the heap.
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.
339
    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;
344
    }
345

	
346
  }; // class FouraryHeap
347

	
348
} // namespace lemon
349

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

	
19
#ifndef LEMON_KARY_HEAP_H
20
#define LEMON_KARY_HEAP_H
21

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

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

	
31
namespace lemon {
32

	
33
  ///\ingroup auxdat
34
  ///
35
  ///\brief A Kary Heap implementation.
36
  ///
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.
42
  ///
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>.
48
  ///
49
  ///\sa FibHeap
50
  ///\sa Dijkstra
51
  ///\author Dorian Batha
52

	
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.
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
75
    /// heap's point of view, but may be useful to the user.
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...
79
    enum State {
80
      IN_HEAP = 0,
81
      PRE_HEAP = -1,
82
      POST_HEAP = -2
83
    };
84

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

	
91
  public:
92
    /// \brief The constructor.
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) {}
99

	
100
    /// \brief The constructor.
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.
106
    ///
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) {}
110

	
111

	
112
    /// The number of items stored in the heap.
113
    ///
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(); }
129

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

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

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

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

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

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

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

	
190
    /// \brief Insert an item into the heap with the given heap.
191
    ///
192
    /// Adds \c i to the heap with priority \c p.
193
    /// \param i The item to insert.
194
    /// \param p The priority of the item.
195
    void push(const Item &i, const Prio &p) { push(Pair(i,p)); }
196

	
197
    /// \brief Returns the item with minimum priority relative to \c Compare.
198
    ///
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; }
203

	
204
    /// \brief Returns the minimum priority relative to \c Compare.
205
    ///
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; }
209

	
210
    /// \brief Deletes the item with minimum priority relative to \c Compare.
211
    ///
212
    /// This method deletes the item with minimum priority relative to \c
213
    /// Compare from the heap.
214
    /// \pre The heap must be non-empty.
215
    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();
220
    }
221

	
222
    /// \brief Deletes \c i from the heap.
223
    ///
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.
227
    void erase(const Item &i) {
228
      int h = iim[i];
229
      int n = data.size()-1;
230
      iim.set(data[h].first, POST_HEAP);
231
      if( h<n ) {
232
        if( less(data[parent(h)], data[n]) )
233
          bubble_down(h, data[n], n);
234
        else
235
          bubble_up(h, data[n]);
236
      }
237
      data.pop_back();
238
    }
239

	
240

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

	
251
    /// \brief \c i gets to the heap with priority \c p independently
252
    /// if \c i was already there.
253
    ///
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.
256
    /// \param i The item.
257
    /// \param p The priority.
258
    void set(const Item &i, const Prio &p) {
259
      int idx = iim[i];
260
      if( idx<0 )
261
        push(i,p);
262
      else if( comp(p, data[idx].second) )
263
        bubble_up(idx, Pair(i,p));
264
      else
265
        bubble_down(idx, Pair(i,p), data.size());
266
    }
267

	
268
    /// \brief Decreases the priority of \c i to \c p.
269
    ///
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.
273
    /// \param i The item.
274
    /// \param p The priority.
275
    void decrease(const Item &i, const Prio &p) {
276
      int idx = iim[i];
277
      bubble_up(idx, Pair(i,p));
278
    }
279

	
280
    /// \brief Increases the priority of \c i to \c p.
281
    ///
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.
285
    /// \param i The item.
286
    /// \param p The priority.
287
    void increase(const Item &i, const Prio &p) {
288
      int idx = iim[i];
289
      bubble_down(idx, Pair(i,p), data.size());
290
    }
291

	
292
    /// \brief Returns if \c item is in, has already been in, or has
293
    /// never been in the heap.
294
    ///
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.
299
    /// \param i The item.
300
    State state(const Item &i) const {
301
      int s = iim[i];
302
      if (s>=0) s=0;
303
      return State(s);
304
    }
305

	
306
    /// \brief Sets the state of the \c item in the heap.
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.
311
    /// \param i The item.
312
    /// \param st The state. It should not be \c IN_HEAP.
313
    void state(const Item& i, State st) {
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;
322
      }
323
    }
324

	
325
    /// \brief Replaces an item in the heap.
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.
331
    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;
336
    }
337

	
338
  }; // class KaryHeap
339

	
340
} // namespace lemon
341

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

	
19
#ifndef LEMON_PAIRING_HEAP_H
20
#define LEMON_PAIRING_HEAP_H
21

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

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

	
30
namespace lemon {
31

	
32
  /// \ingroup auxdat
33
  ///
34
  ///\brief Pairing Heap.
35
  ///
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.
41
  ///
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".
45
  ///
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

	
56
#ifdef DOXYGEN
57
  template <typename _Prio,
58
            typename _ItemIntMap,
59
            typename _Compare>
60
#else
61
  template <typename _Prio,
62
            typename _ItemIntMap,
63
            typename _Compare = std::less<_Prio> >
64
#endif
65
  class PairingHeap {
66
  public:
67
    typedef _ItemIntMap ItemIntMap;
68
    typedef _Prio Prio;
69
    typedef typename ItemIntMap::Key Item;
70
    typedef std::pair<Item,Prio> Pair;
71
    typedef _Compare Compare;
72

	
73
  private:
74
    class store;
75

	
76
    std::vector<store> container;
77
    int minimum;
78
    ItemIntMap &iimap;
79
    Compare comp;
80
    int num_items;
81

	
82
  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
    };
92

	
93
    /// \brief The constructor
94
    ///
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) {}
107

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

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

	
118
    /// \brief Make empty this heap.
119
    ///
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.
124
    void clear() {
125
      container.clear();
126
      minimum = 0;
127
      num_items = 0;
128
    }
129

	
130
    /// \brief \c item gets to the heap with priority \c value independently
131
    /// if \c item was already there.
132
    ///
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.
136
    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
      } else push(item, value);
142
    }
143

	
144
    /// \brief Adds \c item to the heap with priority \c value.
145
    ///
146
    /// Adds \c item to the heap with priority \c value.
147
    /// \pre \c item must not be stored in the heap.
148
    void push (const Item& item, const Prio& value) {
149
      int i=iimap[item];
150
      if( i<0 ) {
151
        int s=container.size();
152
        iimap.set(item, s);
153
        store st;
154
        st.name=item;
155
        container.push_back(st);
156
        i=s;
157
      } 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;
162
      }
163

	
164
      container[i].prio=value;
165

	
166
      if ( num_items!=0 ) {
167
        if ( comp( value, container[minimum].prio) ) {
168
          fuse(i,minimum);
169
          minimum=i;
170
        }
171
        else fuse(minimum,i);
172
      }
173
      else minimum=i;
174

	
175
      ++num_items;
176
    }
177

	
178
    /// \brief Returns the item with minimum priority relative to \c Compare.
179
    ///
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; }
184

	
185
    /// \brief Returns the minimum priority relative to \c Compare.
186
    ///
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; }
190

	
191
    /// \brief Returns the priority of \c item.
192
    ///
193
    /// It returns the priority of \c item.
194
    /// \pre \c item must be in the heap.
195
    const Prio& operator[](const Item& item) const {
196
      return container[iimap[item]].prio;
197
    }
198

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

	
209
      if( -1!=container[minimum].child ) {
210
        i=container[minimum].child;
211
        TreeArray[num_child] = i;
212
        container[i].parent = -1;
213
        container[minimum].child = -1;
214

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

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

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

	
265
      if ( 0==num_child ) {
266
        minimum = container[minimum].child;
267
      }
268

	
269
      --num_items;
270
    }
271

	
272
    /// \brief Deletes \c item from the heap.
273
    ///
274
    /// This method deletes \c item from the heap, if \c item was already
275
    /// stored in the heap. It is quite inefficient in Pairing heaps.
276
    void erase (const Item& item) {
277
      int i=iimap[item];
278
      if ( i>=0 && container[i].in ) {
279
        decrease( item, container[minimum].prio-1 );
280
        pop();
281
      }
282
    }
283

	
284
    /// \brief Decreases the priority of \c item to \c value.
285
    ///
286
    /// This method decreases the priority of \c item to \c value.
287
    /// \pre \c item must be stored in the heap with priority at least \c
288
    ///   value relative to \c Compare.
289
    void decrease (Item item, const Prio& value) {
290
      int i=iimap[item];
291
      container[i].prio=value;
292
      int p=container[i].parent;
293

	
294
      if( container[i].left_child && i!=container[p].child ) {
295
        p=container[p].parent;
296
      }
297

	
298
      if ( p!=-1 && comp(value,container[p].prio) ) {
299
        cut(i,p);
300
        if ( comp(container[minimum].prio,value) ) {
301
          fuse(minimum,i);
302
        } else {
303
          fuse(i,minimum);
304
          minimum=i;
305
        }
306
      }
307
    }
308

	
309
    /// \brief Increases the priority of \c item to \c value.
310
    ///
311
    /// This method sets the priority of \c item to \c value. Though
312
    /// there is no precondition on the priority of \c item, this
313
    /// method should be used only if it is indeed necessary to increase
314
    /// (relative to \c Compare) the priority of \c item, because this
315
    /// method is inefficient.
316
    void increase (Item item, const Prio& value) {
317
      erase(item);
318
      push(item,value);
319
    }
320

	
321
    /// \brief Returns if \c item is in, has already been in, or has never
322
    /// been in the heap.
323
    ///
324
    /// This method returns PRE_HEAP if \c item has never been in the
325
    /// heap, IN_HEAP if it is in the heap at the moment, and POST_HEAP
326
    /// otherwise. In the latter case it is possible that \c item will
327
    /// get back to the heap again.
328
    State state(const Item &item) const {
329
      int i=iimap[item];
330
      if( i>=0 ) {
331
        if( container[i].in ) i=0;
332
        else i=-2;
333
      }
334
      return State(i);
335
    }
336

	
337
    /// \brief Sets the state of the \c item in the heap.
338
    ///
339
    /// Sets the state of the \c item in the heap. It can be used to
340
    /// manually clear the heap when it is important to achive the
341
    /// better time complexity.
342
    /// \param i The item.
343
    /// \param st The state. It should not be \c IN_HEAP.
344
    void state(const Item& i, State st) {
345
      switch (st) {
346
      case POST_HEAP:
347
      case PRE_HEAP:
348
        if (state(i) == IN_HEAP) erase(i);
349
        iimap[i]=st;
350
        break;
351
      case IN_HEAP:
352
        break;
353
      }
354
    }
355

	
356
  private:
357

	
358
    void cut(int a, int b) {
359
      int child_a;
360
      switch (container[a].degree) {
361
        case 2:
362
          child_a = container[container[a].child].parent;
363
          if( container[a].left_child ) {
364
            container[child_a].left_child=true;
365
            container[b].child=child_a;
366
            container[child_a].parent=container[a].parent;
367
          }
368
          else {
369
            container[child_a].left_child=false;
370
            container[child_a].parent=b;
371
            if( a!=container[b].child )
372
              container[container[b].child].parent=child_a;
373
            else
374
              container[b].child=child_a;
375
          }
376
          --container[a].degree;
377
          container[container[a].child].parent=a;
378
          break;
379

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

	
413
        case 0:
414
          --container[b].degree;
415
          if( container[a].left_child ) {
416
            container[b].child =
417
              (0!=container[b].degree) ? container[a].parent : -1;
418
          } else {
419
            if( 0!=container[b].degree )
420
              container[container[b].child].parent=b;
421
            else
422
              container[b].child=-1;
423
          }
424
          break;
425
      }
426
      container[a].parent=-1;
427
      container[a].left_child=false;
428
    }
429

	
430
    void fuse(int a, int b) {
431
      int child_a = container[a].child;
432
      int child_b = container[b].child;
433
      container[a].child=b;
434
      container[b].parent=a;
435
      container[b].left_child=true;
436

	
437
      if( -1!=child_a ) {
438
        container[b].child=child_a;
439
        container[child_a].parent=b;
440
        container[child_a].left_child=false;
441
        ++container[b].degree;
442

	
443
        if( -1!=child_b ) {
444
           container[b].child=child_b;
445
           container[child_b].parent=child_a;
446
        }
447
      }
448
      else { ++container[a].degree; }
449
    }
450

	
451
    class store {
452
      friend class PairingHeap;
453

	
454
      Item name;
455
      int parent;
456
      int child;
457
      bool left_child;
458
      int degree;
459
      bool in;
460
      Prio prio;
461

	
462
      store() : parent(-1), child(-1), left_child(false), degree(0), in(true) {}
463
    };
464
  };
465

	
466
} //namespace lemon
467

	
468
#endif //LEMON_PAIRING_HEAP_H
469

	
Ignore white space 6 line context
1 1
EXTRA_DIST += \
2 2
	lemon/lemon.pc.in \
3 3
	lemon/CMakeLists.txt \
4 4
	lemon/config.h.cmake
5 5

	
6 6
pkgconfig_DATA += lemon/lemon.pc
7 7

	
8 8
lib_LTLIBRARIES += lemon/libemon.la
9 9

	
10 10
lemon_libemon_la_SOURCES = \
11 11
	lemon/arg_parser.cc \
12 12
	lemon/base.cc \
13 13
	lemon/color.cc \
14 14
	lemon/lp_base.cc \
15 15
	lemon/lp_skeleton.cc \
16 16
	lemon/random.cc \
17 17
	lemon/bits/windows.cc
18 18

	
19 19
nodist_lemon_HEADERS = lemon/config.h	
20 20

	
21 21
lemon_libemon_la_CXXFLAGS = \
22 22
	$(AM_CXXFLAGS) \
23 23
	$(GLPK_CFLAGS) \
24 24
	$(CPLEX_CFLAGS) \
25 25
	$(SOPLEX_CXXFLAGS) \
26 26
	$(CLP_CXXFLAGS) \
27 27
	$(CBC_CXXFLAGS)
28 28

	
29 29
lemon_libemon_la_LDFLAGS = \
30 30
	$(GLPK_LIBS) \
31 31
	$(CPLEX_LIBS) \
32 32
	$(SOPLEX_LIBS) \
33 33
	$(CLP_LIBS) \
34 34
	$(CBC_LIBS)
35 35

	
36 36
if HAVE_GLPK
37 37
lemon_libemon_la_SOURCES += lemon/glpk.cc
38 38
endif
39 39

	
40 40
if HAVE_CPLEX
41 41
lemon_libemon_la_SOURCES += lemon/cplex.cc
42 42
endif
43 43

	
44 44
if HAVE_SOPLEX
45 45
lemon_libemon_la_SOURCES += lemon/soplex.cc
46 46
endif
47 47

	
48 48
if HAVE_CLP
49 49
lemon_libemon_la_SOURCES += lemon/clp.cc
50 50
endif
51 51

	
52 52
if HAVE_CBC
53 53
lemon_libemon_la_SOURCES += lemon/cbc.cc
54 54
endif
55 55

	
56 56
lemon_HEADERS += \
57 57
	lemon/adaptors.h \
58 58
	lemon/arg_parser.h \
59 59
	lemon/assert.h \
60 60
	lemon/bfs.h \
61 61
	lemon/bin_heap.h \
62
	lemon/binom_heap.h \
62 63
	lemon/bucket_heap.h \
63 64
	lemon/cbc.h \
64 65
	lemon/circulation.h \
65 66
	lemon/clp.h \
66 67
	lemon/color.h \
67 68
	lemon/concept_check.h \
68 69
	lemon/connectivity.h \
69 70
	lemon/counter.h \
70 71
	lemon/core.h \
71 72
	lemon/cplex.h \
72 73
	lemon/dfs.h \
73 74
	lemon/dijkstra.h \
74 75
	lemon/dim2.h \
75 76
	lemon/dimacs.h \
76 77
	lemon/edge_set.h \
77 78
	lemon/elevator.h \
78 79
	lemon/error.h \
79 80
	lemon/euler.h \
80 81
	lemon/fib_heap.h \
82
	lemon/fourary_heap.h \
81 83
	lemon/full_graph.h \
82 84
	lemon/glpk.h \
83 85
	lemon/gomory_hu.h \
84 86
	lemon/graph_to_eps.h \
85 87
	lemon/grid_graph.h \
86 88
	lemon/hypercube_graph.h \
89
	lemon/kary_heap.h \
87 90
	lemon/kruskal.h \
88 91
	lemon/hao_orlin.h \
89 92
	lemon/lgf_reader.h \
90 93
	lemon/lgf_writer.h \
91 94
	lemon/list_graph.h \
92 95
	lemon/lp.h \
93 96
	lemon/lp_base.h \
94 97
	lemon/lp_skeleton.h \
95 98
	lemon/list_graph.h \
96 99
	lemon/maps.h \
97 100
	lemon/matching.h \
98 101
	lemon/math.h \
99 102
	lemon/min_cost_arborescence.h \
100 103
	lemon/nauty_reader.h \
101 104
	lemon/network_simplex.h \
105
	lemon/pairing_heap.h \
102 106
	lemon/path.h \
103 107
	lemon/preflow.h \
104 108
	lemon/radix_heap.h \
105 109
	lemon/radix_sort.h \
106 110
	lemon/random.h \
107 111
	lemon/smart_graph.h \
108 112
	lemon/soplex.h \
109 113
	lemon/suurballe.h \
110 114
	lemon/time_measure.h \
111 115
	lemon/tolerance.h \
112 116
	lemon/unionfind.h \
113 117
	lemon/bits/windows.h
114 118

	
115 119
bits_HEADERS += \
116 120
	lemon/bits/alteration_notifier.h \
117 121
	lemon/bits/array_map.h \
118 122
	lemon/bits/bezier.h \
119 123
	lemon/bits/default_map.h \
120 124
	lemon/bits/edge_set_extender.h \
121 125
	lemon/bits/enable_if.h \
122 126
	lemon/bits/graph_adaptor_extender.h \
123 127
	lemon/bits/graph_extender.h \
124 128
	lemon/bits/map_extender.h \
125 129
	lemon/bits/path_dump.h \
126 130
	lemon/bits/solver_bits.h \
127 131
	lemon/bits/traits.h \
128 132
	lemon/bits/variant.h \
129 133
	lemon/bits/vector_map.h
130 134

	
131 135
concept_HEADERS += \
132 136
	lemon/concepts/digraph.h \
133 137
	lemon/concepts/graph.h \
134 138
	lemon/concepts/graph_components.h \
135 139
	lemon/concepts/heap.h \
136 140
	lemon/concepts/maps.h \
137 141
	lemon/concepts/path.h
Ignore white space 6 line context
1 1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 2
 *
3 3
 * This file is a part of LEMON, a generic C++ optimization library.
4 4
 *
5 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
#include <iostream>
20 20
#include <fstream>
21 21
#include <string>
22 22
#include <vector>
23 23

	
24 24
#include <lemon/concept_check.h>
25 25
#include <lemon/concepts/heap.h>
26 26

	
27 27
#include <lemon/smart_graph.h>
28

	
29 28
#include <lemon/lgf_reader.h>
30 29
#include <lemon/dijkstra.h>
31 30
#include <lemon/maps.h>
32 31

	
33 32
#include <lemon/bin_heap.h>
33
#include <lemon/fourary_heap.h>
34
#include <lemon/kary_heap.h>
34 35
#include <lemon/fib_heap.h>
36
#include <lemon/pairing_heap.h>
35 37
#include <lemon/radix_heap.h>
38
#include <lemon/binom_heap.h>
36 39
#include <lemon/bucket_heap.h>
37 40

	
38 41
#include "test_tools.h"
39 42

	
40 43
using namespace lemon;
41 44
using namespace lemon::concepts;
42 45

	
43 46
typedef ListDigraph Digraph;
44 47
DIGRAPH_TYPEDEFS(Digraph);
45 48

	
46 49
char test_lgf[] =
47 50
  "@nodes\n"
48 51
  "label\n"
49 52
  "0\n"
50 53
  "1\n"
51 54
  "2\n"
52 55
  "3\n"
53 56
  "4\n"
54 57
  "5\n"
55 58
  "6\n"
56 59
  "7\n"
57 60
  "8\n"
58 61
  "9\n"
59 62
  "@arcs\n"
60 63
  "                label   capacity\n"
61 64
  "0       5       0       94\n"
62 65
  "3       9       1       11\n"
63 66
  "8       7       2       83\n"
64 67
  "1       2       3       94\n"
65 68
  "5       7       4       35\n"
66 69
  "7       4       5       84\n"
67 70
  "9       5       6       38\n"
68 71
  "0       4       7       96\n"
69 72
  "6       7       8       6\n"
70 73
  "3       1       9       27\n"
71 74
  "5       2       10      77\n"
72 75
  "5       6       11      69\n"
73 76
  "6       5       12      41\n"
74 77
  "4       6       13      70\n"
75 78
  "3       2       14      45\n"
76 79
  "7       9       15      93\n"
77 80
  "5       9       16      50\n"
78 81
  "9       0       17      94\n"
79 82
  "9       6       18      67\n"
80 83
  "0       9       19      86\n"
81 84
  "@attributes\n"
82 85
  "source 3\n";
83 86

	
84 87
int test_seq[] = { 2, 28, 19, 27, 33, 25, 13, 41, 10, 26,  1,  9,  4, 34};
85 88
int test_inc[] = {20, 28, 34, 16,  0, 46, 44,  0, 42, 32, 14,  8,  6, 37};
86 89

	
87 90
int test_len = sizeof(test_seq) / sizeof(test_seq[0]);
88 91

	
89 92
template <typename Heap>
90 93
void heapSortTest() {
91 94
  RangeMap<int> map(test_len, -1);
92

	
93 95
  Heap heap(map);
94 96

	
95 97
  std::vector<int> v(test_len);
96

	
97 98
  for (int i = 0; i < test_len; ++i) {
98 99
    v[i] = test_seq[i];
99 100
    heap.push(i, v[i]);
100 101
  }
101 102
  std::sort(v.begin(), v.end());
102 103
  for (int i = 0; i < test_len; ++i) {
103
    check(v[i] == heap.prio() ,"Wrong order in heap sort.");
104
    check(v[i] == heap.prio(), "Wrong order in heap sort.");
104 105
    heap.pop();
105 106
  }
106 107
}
107 108

	
108 109
template <typename Heap>
109 110
void heapIncreaseTest() {
110 111
  RangeMap<int> map(test_len, -1);
111 112

	
112 113
  Heap heap(map);
113 114

	
114 115
  std::vector<int> v(test_len);
115

	
116 116
  for (int i = 0; i < test_len; ++i) {
117 117
    v[i] = test_seq[i];
118 118
    heap.push(i, v[i]);
119 119
  }
120 120
  for (int i = 0; i < test_len; ++i) {
121 121
    v[i] += test_inc[i];
122 122
    heap.increase(i, v[i]);
123 123
  }
124 124
  std::sort(v.begin(), v.end());
125 125
  for (int i = 0; i < test_len; ++i) {
126
    check(v[i] == heap.prio() ,"Wrong order in heap increase test.");
126
    check(v[i] == heap.prio(), "Wrong order in heap increase test.");
127 127
    heap.pop();
128 128
  }
129 129
}
130 130

	
131

	
132

	
133 131
template <typename Heap>
134 132
void dijkstraHeapTest(const Digraph& digraph, const IntArcMap& length,
135 133
                      Node source) {
136 134

	
137 135
  typename Dijkstra<Digraph, IntArcMap>::template SetStandardHeap<Heap>::
138 136
    Create dijkstra(digraph, length);
139 137

	
140 138
  dijkstra.run(source);
141 139

	
142 140
  for(ArcIt a(digraph); a != INVALID; ++a) {
143 141
    Node s = digraph.source(a);
144 142
    Node t = digraph.target(a);
145 143
    if (dijkstra.reached(s)) {
146 144
      check( dijkstra.dist(t) - dijkstra.dist(s) <= length[a],
147
             "Error in a shortest path tree!");
145
             "Error in shortest path tree.");
148 146
    }
149 147
  }
150 148

	
151 149
  for(NodeIt n(digraph); n != INVALID; ++n) {
152 150
    if ( dijkstra.reached(n) && dijkstra.predArc(n) != INVALID ) {
153 151
      Arc a = dijkstra.predArc(n);
154 152
      Node s = digraph.source(a);
155 153
      check( dijkstra.dist(n) - dijkstra.dist(s) == length[a],
156
             "Error in a shortest path tree!");
154
             "Error in shortest path tree.");
157 155
    }
158 156
  }
159 157

	
160 158
}
161 159

	
162 160
int main() {
163 161

	
164 162
  typedef int Item;
165 163
  typedef int Prio;
166 164
  typedef RangeMap<int> ItemIntMap;
167 165

	
168 166
  Digraph digraph;
169 167
  IntArcMap length(digraph);
170 168
  Node source;
171 169

	
172 170
  std::istringstream input(test_lgf);
173 171
  digraphReader(digraph, input).
174 172
    arcMap("capacity", length).
175 173
    node("source", source).
176 174
    run();
177 175

	
176
  // BinHeap
178 177
  {
179 178
    typedef BinHeap<Prio, ItemIntMap> IntHeap;
180 179
    checkConcept<Heap<Prio, ItemIntMap>, IntHeap>();
181 180
    heapSortTest<IntHeap>();
182 181
    heapIncreaseTest<IntHeap>();
183 182

	
184 183
    typedef BinHeap<Prio, IntNodeMap > NodeHeap;
185 184
    checkConcept<Heap<Prio, IntNodeMap >, NodeHeap>();
186 185
    dijkstraHeapTest<NodeHeap>(digraph, length, source);
187 186
  }
188 187

	
188
  // FouraryHeap
189
  {
190
    typedef FouraryHeap<Prio, ItemIntMap> IntHeap;
191
    checkConcept<Heap<Prio, ItemIntMap>, IntHeap>();
192
    heapSortTest<IntHeap>();
193
    heapIncreaseTest<IntHeap>();
194

	
195
    typedef FouraryHeap<Prio, IntNodeMap > NodeHeap;
196
    checkConcept<Heap<Prio, IntNodeMap >, NodeHeap>();
197
    dijkstraHeapTest<NodeHeap>(digraph, length, source);
198
  }
199

	
200
  // KaryHeap
201
  {
202
    typedef KaryHeap<Prio, ItemIntMap> IntHeap;
203
    checkConcept<Heap<Prio, ItemIntMap>, IntHeap>();
204
    heapSortTest<IntHeap>();
205
    heapIncreaseTest<IntHeap>();
206

	
207
    typedef KaryHeap<Prio, IntNodeMap > NodeHeap;
208
    checkConcept<Heap<Prio, IntNodeMap >, NodeHeap>();
209
    dijkstraHeapTest<NodeHeap>(digraph, length, source);
210
  }
211

	
212
  // FibHeap
189 213
  {
190 214
    typedef FibHeap<Prio, ItemIntMap> IntHeap;
191 215
    checkConcept<Heap<Prio, ItemIntMap>, IntHeap>();
192 216
    heapSortTest<IntHeap>();
193 217
    heapIncreaseTest<IntHeap>();
194 218

	
195 219
    typedef FibHeap<Prio, IntNodeMap > NodeHeap;
196 220
    checkConcept<Heap<Prio, IntNodeMap >, NodeHeap>();
197 221
    dijkstraHeapTest<NodeHeap>(digraph, length, source);
198 222
  }
199 223

	
224
  // PairingHeap
225
//  {
226
//    typedef PairingHeap<Prio, ItemIntMap> IntHeap;
227
//    checkConcept<Heap<Prio, ItemIntMap>, IntHeap>();
228
//    heapSortTest<IntHeap>();
229
//    heapIncreaseTest<IntHeap>();
230
//
231
//    typedef PairingHeap<Prio, IntNodeMap > NodeHeap;
232
//    checkConcept<Heap<Prio, IntNodeMap >, NodeHeap>();
233
//    dijkstraHeapTest<NodeHeap>(digraph, length, source);
234
//  }
235

	
236
  // RadixHeap
200 237
  {
201 238
    typedef RadixHeap<ItemIntMap> IntHeap;
202 239
    checkConcept<Heap<Prio, ItemIntMap>, IntHeap>();
203 240
    heapSortTest<IntHeap>();
204 241
    heapIncreaseTest<IntHeap>();
205 242

	
206 243
    typedef RadixHeap<IntNodeMap > NodeHeap;
207 244
    checkConcept<Heap<Prio, IntNodeMap >, NodeHeap>();
208 245
    dijkstraHeapTest<NodeHeap>(digraph, length, source);
209 246
  }
210 247

	
248
  // BinomHeap
249
  {
250
    typedef BinomHeap<Prio, ItemIntMap> IntHeap;
251
    checkConcept<Heap<Prio, ItemIntMap>, IntHeap>();
252
    heapSortTest<IntHeap>();
253
    heapIncreaseTest<IntHeap>();
254

	
255
    typedef BinomHeap<Prio, IntNodeMap > NodeHeap;
256
    checkConcept<Heap<Prio, IntNodeMap >, NodeHeap>();
257
    dijkstraHeapTest<NodeHeap>(digraph, length, source);
258
  }
259

	
260
  // BucketHeap, SimpleBucketHeap
211 261
  {
212 262
    typedef BucketHeap<ItemIntMap> IntHeap;
213 263
    checkConcept<Heap<Prio, ItemIntMap>, IntHeap>();
214 264
    heapSortTest<IntHeap>();
215 265
    heapIncreaseTest<IntHeap>();
216 266

	
217 267
    typedef BucketHeap<IntNodeMap > NodeHeap;
218 268
    checkConcept<Heap<Prio, IntNodeMap >, NodeHeap>();
219 269
    dijkstraHeapTest<NodeHeap>(digraph, length, source);
270

	
271
    typedef SimpleBucketHeap<ItemIntMap> SimpleIntHeap;
272
    heapSortTest<SimpleIntHeap>();
220 273
  }
221 274

	
222

	
223 275
  return 0;
224 276
}
0 comments (0 inline)