gravatar
deba@inf.elte.hu
deba@inf.elte.hu
Port remaining heaps from SVN -r 3509 (#50) - FibHeap - RadixHeap - BucketHeap - SimpleBucketHeap
0 2 3
default
5 files changed with 1771 insertions and 0 deletions:
↑ Collapse diff ↑
Show white space 4 line context
1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2
 *
3
 * This file is a part of LEMON, a generic C++ optimization library.
4
 *
5
 * Copyright (C) 2003-2009
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_BUCKET_HEAP_H
20
#define LEMON_BUCKET_HEAP_H
21

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

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

	
30
namespace lemon {
31

	
32
  /// \ingroup auxdat
33
  ///
34
  /// \brief A Bucket Heap implementation.
35
  ///
36
  /// This class implements the \e bucket \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. The bucket heap is very simple implementation, it can store
40
  /// only integer priorities and it stores for each priority in the
41
  /// \f$ [0..C) \f$ range a list of items. So it should be used only when
42
  /// the priorities are small. It is not intended to use as dijkstra heap.
43
  ///
44
  /// \param _ItemIntMap A read and writable Item int map, used internally
45
  /// to handle the cross references.
46
  /// \param minimize If the given parameter is true then the heap gives back
47
  /// the lowest priority.
48
  template <typename _ItemIntMap, bool minimize = true >
49
  class BucketHeap {
50

	
51
  public:
52
    /// \e
53
    typedef typename _ItemIntMap::Key Item;
54
    /// \e
55
    typedef int Prio;
56
    /// \e
57
    typedef std::pair<Item, Prio> Pair;
58
    /// \e
59
    typedef _ItemIntMap ItemIntMap;
60

	
61
    /// \brief Type to represent the items states.
62
    ///
63
    /// Each Item element have a state associated to it. It may be "in heap",
64
    /// "pre heap" or "post heap". The latter two are indifferent from the
65
    /// heap's point of view, but may be useful to the user.
66
    ///
67
    /// The ItemIntMap \e should be initialized in such way that it maps
68
    /// PRE_HEAP (-1) to any element to be put in the heap...
69
    enum State {
70
      IN_HEAP = 0,
71
      PRE_HEAP = -1,
72
      POST_HEAP = -2
73
    };
74

	
75
  public:
76
    /// \brief The constructor.
77
    ///
78
    /// The constructor.
79
    /// \param _index should be given to the constructor, since it is used
80
    /// internally to handle the cross references. The value of the map
81
    /// should be PRE_HEAP (-1) for each element.
82
    explicit BucketHeap(ItemIntMap &_index) : index(_index), minimal(0) {}
83

	
84
    /// The number of items stored in the heap.
85
    ///
86
    /// \brief Returns the number of items stored in the heap.
87
    int size() const { return data.size(); }
88

	
89
    /// \brief Checks if the heap stores no items.
90
    ///
91
    /// Returns \c true if and only if the heap stores no items.
92
    bool empty() const { return data.empty(); }
93

	
94
    /// \brief Make empty this heap.
95
    ///
96
    /// Make empty this heap. It does not change the cross reference
97
    /// map.  If you want to reuse a heap what is not surely empty you
98
    /// should first clear the heap and after that you should set the
99
    /// cross reference map for each item to \c PRE_HEAP.
100
    void clear() {
101
      data.clear(); first.clear(); minimal = 0;
102
    }
103

	
104
  private:
105

	
106
    void relocate_last(int idx) {
107
      if (idx + 1 < int(data.size())) {
108
        data[idx] = data.back();
109
        if (data[idx].prev != -1) {
110
          data[data[idx].prev].next = idx;
111
        } else {
112
          first[data[idx].value] = idx;
113
        }
114
        if (data[idx].next != -1) {
115
          data[data[idx].next].prev = idx;
116
        }
117
        index[data[idx].item] = idx;
118
      }
119
      data.pop_back();
120
    }
121

	
122
    void unlace(int idx) {
123
      if (data[idx].prev != -1) {
124
        data[data[idx].prev].next = data[idx].next;
125
      } else {
126
        first[data[idx].value] = data[idx].next;
127
      }
128
      if (data[idx].next != -1) {
129
        data[data[idx].next].prev = data[idx].prev;
130
      }
131
    }
132

	
133
    void lace(int idx) {
134
      if (int(first.size()) <= data[idx].value) {
135
        first.resize(data[idx].value + 1, -1);
136
      }
137
      data[idx].next = first[data[idx].value];
138
      if (data[idx].next != -1) {
139
        data[data[idx].next].prev = idx;
140
      }
141
      first[data[idx].value] = idx;
142
      data[idx].prev = -1;
143
    }
144

	
145
  public:
146
    /// \brief Insert a pair of item and priority into the heap.
147
    ///
148
    /// Adds \c p.first to the heap with priority \c p.second.
149
    /// \param p The pair to insert.
150
    void push(const Pair& p) {
151
      push(p.first, p.second);
152
    }
153

	
154
    /// \brief Insert an item into the heap with the given priority.
155
    ///
156
    /// Adds \c i to the heap with priority \c p.
157
    /// \param i The item to insert.
158
    /// \param p The priority of the item.
159
    void push(const Item &i, const Prio &p) {
160
      int idx = data.size();
161
      index[i] = idx;
162
      data.push_back(BucketItem(i, p));
163
      lace(idx);
164
      if (p < minimal) {
165
        minimal = p;
166
      }
167
    }
168

	
169
    /// \brief Returns the item with minimum priority.
170
    ///
171
    /// This method returns the item with minimum priority.
172
    /// \pre The heap must be nonempty.
173
    Item top() const {
174
      while (first[minimal] == -1) {
175
        ++minimal;
176
      }
177
      return data[first[minimal]].item;
178
    }
179

	
180
    /// \brief Returns the minimum priority.
181
    ///
182
    /// It returns the minimum priority.
183
    /// \pre The heap must be nonempty.
184
    Prio prio() const {
185
      while (first[minimal] == -1) {
186
        ++minimal;
187
      }
188
      return minimal;
189
    }
190

	
191
    /// \brief Deletes the item with minimum priority.
192
    ///
193
    /// This method deletes the item with minimum priority from the heap.
194
    /// \pre The heap must be non-empty.
195
    void pop() {
196
      while (first[minimal] == -1) {
197
        ++minimal;
198
      }
199
      int idx = first[minimal];
200
      index[data[idx].item] = -2;
201
      unlace(idx);
202
      relocate_last(idx);
203
    }
204

	
205
    /// \brief Deletes \c i from the heap.
206
    ///
207
    /// This method deletes item \c i from the heap, if \c i was
208
    /// already stored in the heap.
209
    /// \param i The item to erase.
210
    void erase(const Item &i) {
211
      int idx = index[i];
212
      index[data[idx].item] = -2;
213
      unlace(idx);
214
      relocate_last(idx);
215
    }
216

	
217

	
218
    /// \brief Returns the priority of \c i.
219
    ///
220
    /// This function returns the priority of item \c i.
221
    /// \pre \c i must be in the heap.
222
    /// \param i The item.
223
    Prio operator[](const Item &i) const {
224
      int idx = index[i];
225
      return data[idx].value;
226
    }
227

	
228
    /// \brief \c i gets to the heap with priority \c p independently
229
    /// if \c i was already there.
230
    ///
231
    /// This method calls \ref push(\c i, \c p) if \c i is not stored
232
    /// in the heap and sets the priority of \c i to \c p otherwise.
233
    /// \param i The item.
234
    /// \param p The priority.
235
    void set(const Item &i, const Prio &p) {
236
      int idx = index[i];
237
      if (idx < 0) {
238
        push(i,p);
239
      } else if (p > data[idx].value) {
240
        increase(i, p);
241
      } else {
242
        decrease(i, p);
243
      }
244
    }
245

	
246
    /// \brief Decreases the priority of \c i to \c p.
247
    ///
248
    /// This method decreases the priority of item \c i to \c p.
249
    /// \pre \c i must be stored in the heap with priority at least \c
250
    /// p relative to \c Compare.
251
    /// \param i The item.
252
    /// \param p The priority.
253
    void decrease(const Item &i, const Prio &p) {
254
      int idx = index[i];
255
      unlace(idx);
256
      data[idx].value = p;
257
      if (p < minimal) {
258
        minimal = p;
259
      }
260
      lace(idx);
261
    }
262

	
263
    /// \brief Increases the priority of \c i to \c p.
264
    ///
265
    /// This method sets the priority of item \c i to \c p.
266
    /// \pre \c i must be stored in the heap with priority at most \c
267
    /// p relative to \c Compare.
268
    /// \param i The item.
269
    /// \param p The priority.
270
    void increase(const Item &i, const Prio &p) {
271
      int idx = index[i];
272
      unlace(idx);
273
      data[idx].value = p;
274
      lace(idx);
275
    }
276

	
277
    /// \brief Returns if \c item is in, has already been in, or has
278
    /// never been in the heap.
279
    ///
280
    /// This method returns PRE_HEAP if \c item has never been in the
281
    /// heap, IN_HEAP if it is in the heap at the moment, and POST_HEAP
282
    /// otherwise. In the latter case it is possible that \c item will
283
    /// get back to the heap again.
284
    /// \param i The item.
285
    State state(const Item &i) const {
286
      int idx = index[i];
287
      if (idx >= 0) idx = 0;
288
      return State(idx);
289
    }
290

	
291
    /// \brief Sets the state of the \c item in the heap.
292
    ///
293
    /// Sets the state of the \c item in the heap. It can be used to
294
    /// manually clear the heap when it is important to achive the
295
    /// better time complexity.
296
    /// \param i The item.
297
    /// \param st The state. It should not be \c IN_HEAP.
298
    void state(const Item& i, State st) {
299
      switch (st) {
300
      case POST_HEAP:
301
      case PRE_HEAP:
302
        if (state(i) == IN_HEAP) {
303
          erase(i);
304
        }
305
        index[i] = st;
306
        break;
307
      case IN_HEAP:
308
        break;
309
      }
310
    }
311

	
312
  private:
313

	
314
    struct BucketItem {
315
      BucketItem(const Item& _item, int _value)
316
        : item(_item), value(_value) {}
317

	
318
      Item item;
319
      int value;
320

	
321
      int prev, next;
322
    };
323

	
324
    ItemIntMap& index;
325
    std::vector<int> first;
326
    std::vector<BucketItem> data;
327
    mutable int minimal;
328

	
329
  }; // class BucketHeap
330

	
331

	
332
  template <typename _ItemIntMap>
333
  class BucketHeap<_ItemIntMap, false> {
334

	
335
  public:
336
    typedef typename _ItemIntMap::Key Item;
337
    typedef int Prio;
338
    typedef std::pair<Item, Prio> Pair;
339
    typedef _ItemIntMap ItemIntMap;
340

	
341
    enum State {
342
      IN_HEAP = 0,
343
      PRE_HEAP = -1,
344
      POST_HEAP = -2
345
    };
346

	
347
  public:
348

	
349
    explicit BucketHeap(ItemIntMap &_index) : index(_index), maximal(-1) {}
350

	
351
    int size() const { return data.size(); }
352
    bool empty() const { return data.empty(); }
353

	
354
    void clear() {
355
      data.clear(); first.clear(); maximal = -1;
356
    }
357

	
358
  private:
359

	
360
    void relocate_last(int idx) {
361
      if (idx + 1 != int(data.size())) {
362
        data[idx] = data.back();
363
        if (data[idx].prev != -1) {
364
          data[data[idx].prev].next = idx;
365
        } else {
366
          first[data[idx].value] = idx;
367
        }
368
        if (data[idx].next != -1) {
369
          data[data[idx].next].prev = idx;
370
        }
371
        index[data[idx].item] = idx;
372
      }
373
      data.pop_back();
374
    }
375

	
376
    void unlace(int idx) {
377
      if (data[idx].prev != -1) {
378
        data[data[idx].prev].next = data[idx].next;
379
      } else {
380
        first[data[idx].value] = data[idx].next;
381
      }
382
      if (data[idx].next != -1) {
383
        data[data[idx].next].prev = data[idx].prev;
384
      }
385
    }
386

	
387
    void lace(int idx) {
388
      if (int(first.size()) <= data[idx].value) {
389
        first.resize(data[idx].value + 1, -1);
390
      }
391
      data[idx].next = first[data[idx].value];
392
      if (data[idx].next != -1) {
393
        data[data[idx].next].prev = idx;
394
      }
395
      first[data[idx].value] = idx;
396
      data[idx].prev = -1;
397
    }
398

	
399
  public:
400

	
401
    void push(const Pair& p) {
402
      push(p.first, p.second);
403
    }
404

	
405
    void push(const Item &i, const Prio &p) {
406
      int idx = data.size();
407
      index[i] = idx;
408
      data.push_back(BucketItem(i, p));
409
      lace(idx);
410
      if (data[idx].value > maximal) {
411
        maximal = data[idx].value;
412
      }
413
    }
414

	
415
    Item top() const {
416
      while (first[maximal] == -1) {
417
        --maximal;
418
      }
419
      return data[first[maximal]].item;
420
    }
421

	
422
    Prio prio() const {
423
      while (first[maximal] == -1) {
424
        --maximal;
425
      }
426
      return maximal;
427
    }
428

	
429
    void pop() {
430
      while (first[maximal] == -1) {
431
        --maximal;
432
      }
433
      int idx = first[maximal];
434
      index[data[idx].item] = -2;
435
      unlace(idx);
436
      relocate_last(idx);
437
    }
438

	
439
    void erase(const Item &i) {
440
      int idx = index[i];
441
      index[data[idx].item] = -2;
442
      unlace(idx);
443
      relocate_last(idx);
444
    }
445

	
446
    Prio operator[](const Item &i) const {
447
      int idx = index[i];
448
      return data[idx].value;
449
    }
450

	
451
    void set(const Item &i, const Prio &p) {
452
      int idx = index[i];
453
      if (idx < 0) {
454
        push(i,p);
455
      } else if (p > data[idx].value) {
456
        decrease(i, p);
457
      } else {
458
        increase(i, p);
459
      }
460
    }
461

	
462
    void decrease(const Item &i, const Prio &p) {
463
      int idx = index[i];
464
      unlace(idx);
465
      data[idx].value = p;
466
      if (p > maximal) {
467
        maximal = p;
468
      }
469
      lace(idx);
470
    }
471

	
472
    void increase(const Item &i, const Prio &p) {
473
      int idx = index[i];
474
      unlace(idx);
475
      data[idx].value = p;
476
      lace(idx);
477
    }
478

	
479
    State state(const Item &i) const {
480
      int idx = index[i];
481
      if (idx >= 0) idx = 0;
482
      return State(idx);
483
    }
484

	
485
    void state(const Item& i, State st) {
486
      switch (st) {
487
      case POST_HEAP:
488
      case PRE_HEAP:
489
        if (state(i) == IN_HEAP) {
490
          erase(i);
491
        }
492
        index[i] = st;
493
        break;
494
      case IN_HEAP:
495
        break;
496
      }
497
    }
498

	
499
  private:
500

	
501
    struct BucketItem {
502
      BucketItem(const Item& _item, int _value)
503
        : item(_item), value(_value) {}
504

	
505
      Item item;
506
      int value;
507

	
508
      int prev, next;
509
    };
510

	
511
    ItemIntMap& index;
512
    std::vector<int> first;
513
    std::vector<BucketItem> data;
514
    mutable int maximal;
515

	
516
  }; // class BucketHeap
517

	
518
  /// \ingroup auxdat
519
  ///
520
  /// \brief A Simplified Bucket Heap implementation.
521
  ///
522
  /// This class implements a simplified \e bucket \e heap data
523
  /// structure.  It does not provide some functionality but it faster
524
  /// and simplier data structure than the BucketHeap. The main
525
  /// difference is that the BucketHeap stores for every key a double
526
  /// linked list while this class stores just simple lists. In the
527
  /// other way it does not supports erasing each elements just the
528
  /// minimal and it does not supports key increasing, decreasing.
529
  ///
530
  /// \param _ItemIntMap A read and writable Item int map, used internally
531
  /// to handle the cross references.
532
  /// \param minimize If the given parameter is true then the heap gives back
533
  /// the lowest priority.
534
  ///
535
  /// \sa BucketHeap
536
  template <typename _ItemIntMap, bool minimize = true >
537
  class SimpleBucketHeap {
538

	
539
  public:
540
    typedef typename _ItemIntMap::Key Item;
541
    typedef int Prio;
542
    typedef std::pair<Item, Prio> Pair;
543
    typedef _ItemIntMap ItemIntMap;
544

	
545
    /// \brief Type to represent the items states.
546
    ///
547
    /// Each Item element have a state associated to it. It may be "in heap",
548
    /// "pre heap" or "post heap". The latter two are indifferent from the
549
    /// heap's point of view, but may be useful to the user.
550
    ///
551
    /// The ItemIntMap \e should be initialized in such way that it maps
552
    /// PRE_HEAP (-1) to any element to be put in the heap...
553
    enum State {
554
      IN_HEAP = 0,
555
      PRE_HEAP = -1,
556
      POST_HEAP = -2
557
    };
558

	
559
  public:
560

	
561
    /// \brief The constructor.
562
    ///
563
    /// The constructor.
564
    /// \param _index should be given to the constructor, since it is used
565
    /// internally to handle the cross references. The value of the map
566
    /// should be PRE_HEAP (-1) for each element.
567
    explicit SimpleBucketHeap(ItemIntMap &_index)
568
      : index(_index), free(-1), num(0), minimal(0) {}
569

	
570
    /// \brief Returns the number of items stored in the heap.
571
    ///
572
    /// The number of items stored in the heap.
573
    int size() const { return num; }
574

	
575
    /// \brief Checks if the heap stores no items.
576
    ///
577
    /// Returns \c true if and only if the heap stores no items.
578
    bool empty() const { return num == 0; }
579

	
580
    /// \brief Make empty this heap.
581
    ///
582
    /// Make empty this heap. It does not change the cross reference
583
    /// map.  If you want to reuse a heap what is not surely empty you
584
    /// should first clear the heap and after that you should set the
585
    /// cross reference map for each item to \c PRE_HEAP.
586
    void clear() {
587
      data.clear(); first.clear(); free = -1; num = 0; minimal = 0;
588
    }
589

	
590
    /// \brief Insert a pair of item and priority into the heap.
591
    ///
592
    /// Adds \c p.first to the heap with priority \c p.second.
593
    /// \param p The pair to insert.
594
    void push(const Pair& p) {
595
      push(p.first, p.second);
596
    }
597

	
598
    /// \brief Insert an item into the heap with the given priority.
599
    ///
600
    /// Adds \c i to the heap with priority \c p.
601
    /// \param i The item to insert.
602
    /// \param p The priority of the item.
603
    void push(const Item &i, const Prio &p) {
604
      int idx;
605
      if (free == -1) {
606
        idx = data.size();
607
        data.push_back(BucketItem(i));
608
      } else {
609
        idx = free;
610
        free = data[idx].next;
611
        data[idx].item = i;
612
      }
613
      index[i] = idx;
614
      if (p >= int(first.size())) first.resize(p + 1, -1);
615
      data[idx].next = first[p];
616
      first[p] = idx;
617
      if (p < minimal) {
618
        minimal = p;
619
      }
620
      ++num;
621
    }
622

	
623
    /// \brief Returns the item with minimum priority.
624
    ///
625
    /// This method returns the item with minimum priority.
626
    /// \pre The heap must be nonempty.
627
    Item top() const {
628
      while (first[minimal] == -1) {
629
        ++minimal;
630
      }
631
      return data[first[minimal]].item;
632
    }
633

	
634
    /// \brief Returns the minimum priority.
635
    ///
636
    /// It returns the minimum priority.
637
    /// \pre The heap must be nonempty.
638
    Prio prio() const {
639
      while (first[minimal] == -1) {
640
        ++minimal;
641
      }
642
      return minimal;
643
    }
644

	
645
    /// \brief Deletes the item with minimum priority.
646
    ///
647
    /// This method deletes the item with minimum priority from the heap.
648
    /// \pre The heap must be non-empty.
649
    void pop() {
650
      while (first[minimal] == -1) {
651
        ++minimal;
652
      }
653
      int idx = first[minimal];
654
      index[data[idx].item] = -2;
655
      first[minimal] = data[idx].next;
656
      data[idx].next = free;
657
      free = idx;
658
      --num;
659
    }
660

	
661
    /// \brief Returns the priority of \c i.
662
    ///
663
    /// This function returns the priority of item \c i.
664
    /// \warning This operator is not a constant time function
665
    /// because it scans the whole data structure to find the proper
666
    /// value.
667
    /// \pre \c i must be in the heap.
668
    /// \param i The item.
669
    Prio operator[](const Item &i) const {
670
      for (int k = 0; k < first.size(); ++k) {
671
        int idx = first[k];
672
        while (idx != -1) {
673
          if (data[idx].item == i) {
674
            return k;
675
          }
676
          idx = data[idx].next;
677
        }
678
      }
679
      return -1;
680
    }
681

	
682
    /// \brief Returns if \c item is in, has already been in, or has
683
    /// never been in the heap.
684
    ///
685
    /// This method returns PRE_HEAP if \c item has never been in the
686
    /// heap, IN_HEAP if it is in the heap at the moment, and POST_HEAP
687
    /// otherwise. In the latter case it is possible that \c item will
688
    /// get back to the heap again.
689
    /// \param i The item.
690
    State state(const Item &i) const {
691
      int idx = index[i];
692
      if (idx >= 0) idx = 0;
693
      return State(idx);
694
    }
695

	
696
  private:
697

	
698
    struct BucketItem {
699
      BucketItem(const Item& _item)
700
        : item(_item) {}
701

	
702
      Item item;
703
      int next;
704
    };
705

	
706
    ItemIntMap& index;
707
    std::vector<int> first;
708
    std::vector<BucketItem> data;
709
    int free, num;
710
    mutable int minimal;
711

	
712
  }; // class SimpleBucketHeap
713

	
714
  template <typename _ItemIntMap>
715
  class SimpleBucketHeap<_ItemIntMap, false> {
716

	
717
  public:
718
    typedef typename _ItemIntMap::Key Item;
719
    typedef int Prio;
720
    typedef std::pair<Item, Prio> Pair;
721
    typedef _ItemIntMap ItemIntMap;
722

	
723
    enum State {
724
      IN_HEAP = 0,
725
      PRE_HEAP = -1,
726
      POST_HEAP = -2
727
    };
728

	
729
  public:
730

	
731
    explicit SimpleBucketHeap(ItemIntMap &_index)
732
      : index(_index), free(-1), num(0), maximal(0) {}
733

	
734
    int size() const { return num; }
735

	
736
    bool empty() const { return num == 0; }
737

	
738
    void clear() {
739
      data.clear(); first.clear(); free = -1; num = 0; maximal = 0;
740
    }
741

	
742
    void push(const Pair& p) {
743
      push(p.first, p.second);
744
    }
745

	
746
    void push(const Item &i, const Prio &p) {
747
      int idx;
748
      if (free == -1) {
749
        idx = data.size();
750
        data.push_back(BucketItem(i));
751
      } else {
752
        idx = free;
753
        free = data[idx].next;
754
        data[idx].item = i;
755
      }
756
      index[i] = idx;
757
      if (p >= int(first.size())) first.resize(p + 1, -1);
758
      data[idx].next = first[p];
759
      first[p] = idx;
760
      if (p > maximal) {
761
        maximal = p;
762
      }
763
      ++num;
764
    }
765

	
766
    Item top() const {
767
      while (first[maximal] == -1) {
768
        --maximal;
769
      }
770
      return data[first[maximal]].item;
771
    }
772

	
773
    Prio prio() const {
774
      while (first[maximal] == -1) {
775
        --maximal;
776
      }
777
      return maximal;
778
    }
779

	
780
    void pop() {
781
      while (first[maximal] == -1) {
782
        --maximal;
783
      }
784
      int idx = first[maximal];
785
      index[data[idx].item] = -2;
786
      first[maximal] = data[idx].next;
787
      data[idx].next = free;
788
      free = idx;
789
      --num;
790
    }
791

	
792
    Prio operator[](const Item &i) const {
793
      for (int k = 0; k < first.size(); ++k) {
794
        int idx = first[k];
795
        while (idx != -1) {
796
          if (data[idx].item == i) {
797
            return k;
798
          }
799
          idx = data[idx].next;
800
        }
801
      }
802
      return -1;
803
    }
804

	
805
    State state(const Item &i) const {
806
      int idx = index[i];
807
      if (idx >= 0) idx = 0;
808
      return State(idx);
809
    }
810

	
811
  private:
812

	
813
    struct BucketItem {
814
      BucketItem(const Item& _item) : item(_item) {}
815

	
816
      Item item;
817

	
818
      int next;
819
    };
820

	
821
    ItemIntMap& index;
822
    std::vector<int> first;
823
    std::vector<BucketItem> data;
824
    int free, num;
825
    mutable int maximal;
826

	
827
  };
828

	
829
}
830

	
831
#endif
Show white space 4 line context
1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2
 *
3
 * This file is a part of LEMON, a generic C++ optimization library.
4
 *
5
 * Copyright (C) 2003-2009
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_FIB_HEAP_H
20
#define LEMON_FIB_HEAP_H
21

	
22
///\file
23
///\ingroup auxdat
24
///\brief Fibonacci 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 Fibonacci Heap.
35
  ///
36
  ///This class implements the \e Fibonacci \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 Fibonacci
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
#ifdef DOXYGEN
55
  template <typename _Prio,
56
            typename _ItemIntMap,
57
            typename _Compare>
58
#else
59
  template <typename _Prio,
60
            typename _ItemIntMap,
61
            typename _Compare = std::less<_Prio> >
62
#endif
63
  class FibHeap {
64
  public:
65
    ///\e
66
    typedef _ItemIntMap ItemIntMap;
67
    ///\e
68
    typedef _Prio Prio;
69
    ///\e
70
    typedef typename ItemIntMap::Key Item;
71
    ///\e
72
    typedef std::pair<Item,Prio> Pair;
73
    ///\e
74
    typedef _Compare Compare;
75

	
76
  private:
77
    class store;
78

	
79
    std::vector<store> container;
80
    int minimum;
81
    ItemIntMap &iimap;
82
    Compare comp;
83
    int num_items;
84

	
85
  public:
86
    ///Status of the nodes
87
    enum State {
88
      ///The node is in the heap
89
      IN_HEAP = 0,
90
      ///The node has never been in the heap
91
      PRE_HEAP = -1,
92
      ///The node was in the heap but it got out of it
93
      POST_HEAP = -2
94
    };
95

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

	
103
    /// \brief The constructor
104
    ///
105
    /// \c _iimap should be given to the constructor, since it is used
106
    /// internally to handle the cross references. \c _comp is an
107
    /// object for ordering of the priorities.
108
    FibHeap(ItemIntMap &_iimap, const Compare &_comp)
109
      : minimum(0), iimap(_iimap), comp(_comp), num_items() {}
110

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

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

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

	
131
    /// \brief \c item gets to the heap with priority \c value independently
132
    /// if \c item was already there.
133
    ///
134
    /// This method calls \ref push(\c item, \c value) if \c item is not
135
    /// stored in the heap and it calls \ref decrease(\c item, \c value) or
136
    /// \ref increase(\c item, \c value) otherwise.
137
    void set (const Item& item, const Prio& value) {
138
      int i=iimap[item];
139
      if ( i >= 0 && container[i].in ) {
140
        if ( comp(value, container[i].prio) ) decrease(item, value);
141
        if ( comp(container[i].prio, value) ) increase(item, value);
142
      } else push(item, value);
143
    }
144

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

	
165
      if ( num_items ) {
166
        container[container[minimum].right_neighbor].left_neighbor=i;
167
        container[i].right_neighbor=container[minimum].right_neighbor;
168
        container[minimum].right_neighbor=i;
169
        container[i].left_neighbor=minimum;
170
        if ( comp( value, container[minimum].prio) ) minimum=i;
171
      } else {
172
        container[i].right_neighbor=container[i].left_neighbor=i;
173
        minimum=i;
174
      }
175
      container[i].prio=value;
176
      ++num_items;
177
    }
178

	
179
    /// \brief Returns the item with minimum priority relative to \c Compare.
180
    ///
181
    /// This method returns the item with minimum priority relative to \c
182
    /// Compare.
183
    /// \pre The heap must be nonempty.
184
    Item top() const { return container[minimum].name; }
185

	
186
    /// \brief Returns the minimum priority relative to \c Compare.
187
    ///
188
    /// It returns the minimum priority relative to \c Compare.
189
    /// \pre The heap must be nonempty.
190
    const Prio& prio() const { return container[minimum].prio; }
191

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

	
200
    /// \brief Deletes the item with minimum priority relative to \c Compare.
201
    ///
202
    /// This method deletes the item with minimum priority relative to \c
203
    /// Compare from the heap.
204
    /// \pre The heap must be non-empty.
205
    void pop() {
206
      /*The first case is that there are only one root.*/
207
      if ( container[minimum].left_neighbor==minimum ) {
208
        container[minimum].in=false;
209
        if ( container[minimum].degree!=0 ) {
210
          makeroot(container[minimum].child);
211
          minimum=container[minimum].child;
212
          balance();
213
        }
214
      } else {
215
        int right=container[minimum].right_neighbor;
216
        unlace(minimum);
217
        container[minimum].in=false;
218
        if ( container[minimum].degree > 0 ) {
219
          int left=container[minimum].left_neighbor;
220
          int child=container[minimum].child;
221
          int last_child=container[child].left_neighbor;
222

	
223
          makeroot(child);
224

	
225
          container[left].right_neighbor=child;
226
          container[child].left_neighbor=left;
227
          container[right].left_neighbor=last_child;
228
          container[last_child].right_neighbor=right;
229
        }
230
        minimum=right;
231
        balance();
232
      } // the case where there are more roots
233
      --num_items;
234
    }
235

	
236
    /// \brief Deletes \c item from the heap.
237
    ///
238
    /// This method deletes \c item from the heap, if \c item was already
239
    /// stored in the heap. It is quite inefficient in Fibonacci heaps.
240
    void erase (const Item& item) {
241
      int i=iimap[item];
242

	
243
      if ( i >= 0 && container[i].in ) {
244
        if ( container[i].parent!=-1 ) {
245
          int p=container[i].parent;
246
          cut(i,p);
247
          cascade(p);
248
        }
249
        minimum=i;     //As if its prio would be -infinity
250
        pop();
251
      }
252
    }
253

	
254
    /// \brief Decreases the priority of \c item to \c value.
255
    ///
256
    /// This method decreases the priority of \c item to \c value.
257
    /// \pre \c item must be stored in the heap with priority at least \c
258
    ///   value relative to \c Compare.
259
    void decrease (Item item, const Prio& value) {
260
      int i=iimap[item];
261
      container[i].prio=value;
262
      int p=container[i].parent;
263

	
264
      if ( p!=-1 && comp(value, container[p].prio) ) {
265
        cut(i,p);
266
        cascade(p);
267
      }
268
      if ( comp(value, container[minimum].prio) ) minimum=i;
269
    }
270

	
271
    /// \brief Increases the priority of \c item to \c value.
272
    ///
273
    /// This method sets the priority of \c item to \c value. Though
274
    /// there is no precondition on the priority of \c item, this
275
    /// method should be used only if it is indeed necessary to increase
276
    /// (relative to \c Compare) the priority of \c item, because this
277
    /// method is inefficient.
278
    void increase (Item item, const Prio& value) {
279
      erase(item);
280
      push(item, value);
281
    }
282

	
283

	
284
    /// \brief Returns if \c item is in, has already been in, or has never
285
    /// been in the heap.
286
    ///
287
    /// This method returns PRE_HEAP if \c item has never been in the
288
    /// heap, IN_HEAP if it is in the heap at the moment, and POST_HEAP
289
    /// otherwise. In the latter case it is possible that \c item will
290
    /// get back to the heap again.
291
    State state(const Item &item) const {
292
      int i=iimap[item];
293
      if( i>=0 ) {
294
        if ( container[i].in ) i=0;
295
        else i=-2;
296
      }
297
      return State(i);
298
    }
299

	
300
    /// \brief Sets the state of the \c item in the heap.
301
    ///
302
    /// Sets the state of the \c item in the heap. It can be used to
303
    /// manually clear the heap when it is important to achive the
304
    /// better time complexity.
305
    /// \param i The item.
306
    /// \param st The state. It should not be \c IN_HEAP.
307
    void state(const Item& i, State st) {
308
      switch (st) {
309
      case POST_HEAP:
310
      case PRE_HEAP:
311
        if (state(i) == IN_HEAP) {
312
          erase(i);
313
        }
314
        iimap[i] = st;
315
        break;
316
      case IN_HEAP:
317
        break;
318
      }
319
    }
320

	
321
  private:
322

	
323
    void balance() {
324

	
325
      int maxdeg=int( std::floor( 2.08*log(double(container.size()))))+1;
326

	
327
      std::vector<int> A(maxdeg,-1);
328

	
329
      /*
330
       *Recall that now minimum does not point to the minimum prio element.
331
       *We set minimum to this during balance().
332
       */
333
      int anchor=container[minimum].left_neighbor;
334
      int next=minimum;
335
      bool end=false;
336

	
337
      do {
338
        int active=next;
339
        if ( anchor==active ) end=true;
340
        int d=container[active].degree;
341
        next=container[active].right_neighbor;
342

	
343
        while (A[d]!=-1) {
344
          if( comp(container[active].prio, container[A[d]].prio) ) {
345
            fuse(active,A[d]);
346
          } else {
347
            fuse(A[d],active);
348
            active=A[d];
349
          }
350
          A[d]=-1;
351
          ++d;
352
        }
353
        A[d]=active;
354
      } while ( !end );
355

	
356

	
357
      while ( container[minimum].parent >=0 )
358
        minimum=container[minimum].parent;
359
      int s=minimum;
360
      int m=minimum;
361
      do {
362
        if ( comp(container[s].prio, container[minimum].prio) ) minimum=s;
363
        s=container[s].right_neighbor;
364
      } while ( s != m );
365
    }
366

	
367
    void makeroot(int c) {
368
      int s=c;
369
      do {
370
        container[s].parent=-1;
371
        s=container[s].right_neighbor;
372
      } while ( s != c );
373
    }
374

	
375
    void cut(int a, int b) {
376
      /*
377
       *Replacing a from the children of b.
378
       */
379
      --container[b].degree;
380

	
381
      if ( container[b].degree !=0 ) {
382
        int child=container[b].child;
383
        if ( child==a )
384
          container[b].child=container[child].right_neighbor;
385
        unlace(a);
386
      }
387

	
388

	
389
      /*Lacing a to the roots.*/
390
      int right=container[minimum].right_neighbor;
391
      container[minimum].right_neighbor=a;
392
      container[a].left_neighbor=minimum;
393
      container[a].right_neighbor=right;
394
      container[right].left_neighbor=a;
395

	
396
      container[a].parent=-1;
397
      container[a].marked=false;
398
    }
399

	
400
    void cascade(int a) {
401
      if ( container[a].parent!=-1 ) {
402
        int p=container[a].parent;
403

	
404
        if ( container[a].marked==false ) container[a].marked=true;
405
        else {
406
          cut(a,p);
407
          cascade(p);
408
        }
409
      }
410
    }
411

	
412
    void fuse(int a, int b) {
413
      unlace(b);
414

	
415
      /*Lacing b under a.*/
416
      container[b].parent=a;
417

	
418
      if (container[a].degree==0) {
419
        container[b].left_neighbor=b;
420
        container[b].right_neighbor=b;
421
        container[a].child=b;
422
      } else {
423
        int child=container[a].child;
424
        int last_child=container[child].left_neighbor;
425
        container[child].left_neighbor=b;
426
        container[b].right_neighbor=child;
427
        container[last_child].right_neighbor=b;
428
        container[b].left_neighbor=last_child;
429
      }
430

	
431
      ++container[a].degree;
432

	
433
      container[b].marked=false;
434
    }
435

	
436
    /*
437
     *It is invoked only if a has siblings.
438
     */
439
    void unlace(int a) {
440
      int leftn=container[a].left_neighbor;
441
      int rightn=container[a].right_neighbor;
442
      container[leftn].right_neighbor=rightn;
443
      container[rightn].left_neighbor=leftn;
444
    }
445

	
446

	
447
    class store {
448
      friend class FibHeap;
449

	
450
      Item name;
451
      int parent;
452
      int left_neighbor;
453
      int right_neighbor;
454
      int child;
455
      int degree;
456
      bool marked;
457
      bool in;
458
      Prio prio;
459

	
460
      store() : parent(-1), child(-1), degree(), marked(false), in(true) {}
461
    };
462
  };
463

	
464
} //namespace lemon
465

	
466
#endif //LEMON_FIB_HEAP_H
467

	
Show white space 4 line context
1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2
 *
3
 * This file is a part of LEMON, a generic C++ optimization library.
4
 *
5
 * Copyright (C) 2003-2009
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_RADIX_HEAP_H
20
#define LEMON_RADIX_HEAP_H
21

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

	
26
#include <vector>
27
#include <lemon/error.h>
28

	
29
namespace lemon {
30

	
31

	
32
  /// \ingroup auxdata
33
  ///
34
  /// \brief A Radix Heap implementation.
35
  ///
36
  /// This class implements the \e radix \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. This heap type can store only items with \e int priority.
40
  /// In a heap one can change the priority of an item, add or erase an
41
  /// item, but the priority cannot be decreased under the last removed
42
  /// item's priority.
43
  ///
44
  /// \param _ItemIntMap A read and writable Item int map, used internally
45
  /// to handle the cross references.
46
  ///
47
  /// \see BinHeap
48
  /// \see Dijkstra
49
  template <typename _ItemIntMap>
50
  class RadixHeap {
51

	
52
  public:
53
    typedef typename _ItemIntMap::Key Item;
54
    typedef int Prio;
55
    typedef _ItemIntMap ItemIntMap;
56

	
57
    /// \brief Exception thrown by RadixHeap.
58
    ///
59
    /// This Exception is thrown when a smaller priority
60
    /// is inserted into the \e RadixHeap then the last time erased.
61
    /// \see RadixHeap
62

	
63
    class UnderFlowPriorityError : public Exception {
64
    public:
65
      virtual const char* what() const throw() {
66
        return "lemon::RadixHeap::UnderFlowPriorityError";
67
      }
68
    };
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

	
86
    struct RadixItem {
87
      int prev, next, box;
88
      Item item;
89
      int prio;
90
      RadixItem(Item _item, int _prio) : item(_item), prio(_prio) {}
91
    };
92

	
93
    struct RadixBox {
94
      int first;
95
      int min, size;
96
      RadixBox(int _min, int _size) : first(-1), min(_min), size(_size) {}
97
    };
98

	
99
    std::vector<RadixItem> data;
100
    std::vector<RadixBox> boxes;
101

	
102
    ItemIntMap &iim;
103

	
104

	
105
  public:
106
    /// \brief The constructor.
107
    ///
108
    /// The constructor.
109
    ///
110
    /// \param _iim It should be given to the constructor, since it is used
111
    /// internally to handle the cross references. The value of the map
112
    /// should be PRE_HEAP (-1) for each element.
113
    ///
114
    /// \param minimal The initial minimal value of the heap.
115
    /// \param capacity It determines the initial capacity of the heap.
116
    RadixHeap(ItemIntMap &_iim, int minimal = 0, int capacity = 0)
117
      : iim(_iim) {
118
      boxes.push_back(RadixBox(minimal, 1));
119
      boxes.push_back(RadixBox(minimal + 1, 1));
120
      while (lower(boxes.size() - 1, capacity + minimal - 1)) {
121
        extend();
122
      }
123
    }
124

	
125
    /// The number of items stored in the heap.
126
    ///
127
    /// \brief Returns the number of items stored in the heap.
128
    int size() const { return data.size(); }
129
    /// \brief Checks if the heap stores no items.
130
    ///
131
    /// Returns \c true if and only if the heap stores no items.
132
    bool empty() const { return data.empty(); }
133

	
134
    /// \brief Make empty this heap.
135
    ///
136
    /// Make empty this heap. It does not change the cross reference
137
    /// map.  If you want to reuse a heap what is not surely empty you
138
    /// should first clear the heap and after that you should set the
139
    /// cross reference map for each item to \c PRE_HEAP.
140
    void clear(int minimal = 0, int capacity = 0) {
141
      data.clear(); boxes.clear();
142
      boxes.push_back(RadixBox(minimal, 1));
143
      boxes.push_back(RadixBox(minimal + 1, 1));
144
      while (lower(boxes.size() - 1, capacity + minimal - 1)) {
145
        extend();
146
      }
147
    }
148

	
149
  private:
150

	
151
    bool upper(int box, Prio pr) {
152
      return pr < boxes[box].min;
153
    }
154

	
155
    bool lower(int box, Prio pr) {
156
      return pr >= boxes[box].min + boxes[box].size;
157
    }
158

	
159
    /// \brief Remove item from the box list.
160
    void remove(int index) {
161
      if (data[index].prev >= 0) {
162
        data[data[index].prev].next = data[index].next;
163
      } else {
164
        boxes[data[index].box].first = data[index].next;
165
      }
166
      if (data[index].next >= 0) {
167
        data[data[index].next].prev = data[index].prev;
168
      }
169
    }
170

	
171
    /// \brief Insert item into the box list.
172
    void insert(int box, int index) {
173
      if (boxes[box].first == -1) {
174
        boxes[box].first = index;
175
        data[index].next = data[index].prev = -1;
176
      } else {
177
        data[index].next = boxes[box].first;
178
        data[boxes[box].first].prev = index;
179
        data[index].prev = -1;
180
        boxes[box].first = index;
181
      }
182
      data[index].box = box;
183
    }
184

	
185
    /// \brief Add a new box to the box list.
186
    void extend() {
187
      int min = boxes.back().min + boxes.back().size;
188
      int bs = 2 * boxes.back().size;
189
      boxes.push_back(RadixBox(min, bs));
190
    }
191

	
192
    /// \brief Move an item up into the proper box.
193
    void bubble_up(int index) {
194
      if (!lower(data[index].box, data[index].prio)) return;
195
      remove(index);
196
      int box = findUp(data[index].box, data[index].prio);
197
      insert(box, index);
198
    }
199

	
200
    /// \brief Find up the proper box for the item with the given prio.
201
    int findUp(int start, int pr) {
202
      while (lower(start, pr)) {
203
        if (++start == int(boxes.size())) {
204
          extend();
205
        }
206
      }
207
      return start;
208
    }
209

	
210
    /// \brief Move an item down into the proper box.
211
    void bubble_down(int index) {
212
      if (!upper(data[index].box, data[index].prio)) return;
213
      remove(index);
214
      int box = findDown(data[index].box, data[index].prio);
215
      insert(box, index);
216
    }
217

	
218
    /// \brief Find up the proper box for the item with the given prio.
219
    int findDown(int start, int pr) {
220
      while (upper(start, pr)) {
221
        if (--start < 0) throw UnderFlowPriorityError();
222
      }
223
      return start;
224
    }
225

	
226
    /// \brief Find the first not empty box.
227
    int findFirst() {
228
      int first = 0;
229
      while (boxes[first].first == -1) ++first;
230
      return first;
231
    }
232

	
233
    /// \brief Gives back the minimal prio of the box.
234
    int minValue(int box) {
235
      int min = data[boxes[box].first].prio;
236
      for (int k = boxes[box].first; k != -1; k = data[k].next) {
237
        if (data[k].prio < min) min = data[k].prio;
238
      }
239
      return min;
240
    }
241

	
242
    /// \brief Rearrange the items of the heap and makes the
243
    /// first box not empty.
244
    void moveDown() {
245
      int box = findFirst();
246
      if (box == 0) return;
247
      int min = minValue(box);
248
      for (int i = 0; i <= box; ++i) {
249
        boxes[i].min = min;
250
        min += boxes[i].size;
251
      }
252
      int curr = boxes[box].first, next;
253
      while (curr != -1) {
254
        next = data[curr].next;
255
        bubble_down(curr);
256
        curr = next;
257
      }
258
    }
259

	
260
    void relocate_last(int index) {
261
      if (index != int(data.size()) - 1) {
262
        data[index] = data.back();
263
        if (data[index].prev != -1) {
264
          data[data[index].prev].next = index;
265
        } else {
266
          boxes[data[index].box].first = index;
267
        }
268
        if (data[index].next != -1) {
269
          data[data[index].next].prev = index;
270
        }
271
        iim[data[index].item] = index;
272
      }
273
      data.pop_back();
274
    }
275

	
276
  public:
277

	
278
    /// \brief Insert an item into the heap with the given priority.
279
    ///
280
    /// Adds \c i to the heap with priority \c p.
281
    /// \param i The item to insert.
282
    /// \param p The priority of the item.
283
    void push(const Item &i, const Prio &p) {
284
      int n = data.size();
285
      iim.set(i, n);
286
      data.push_back(RadixItem(i, p));
287
      while (lower(boxes.size() - 1, p)) {
288
        extend();
289
      }
290
      int box = findDown(boxes.size() - 1, p);
291
      insert(box, n);
292
    }
293

	
294
    /// \brief Returns the item with minimum priority.
295
    ///
296
    /// This method returns the item with minimum priority.
297
    /// \pre The heap must be nonempty.
298
    Item top() const {
299
      const_cast<RadixHeap<ItemIntMap>&>(*this).moveDown();
300
      return data[boxes[0].first].item;
301
    }
302

	
303
    /// \brief Returns the minimum priority.
304
    ///
305
    /// It returns the minimum priority.
306
    /// \pre The heap must be nonempty.
307
    Prio prio() const {
308
      const_cast<RadixHeap<ItemIntMap>&>(*this).moveDown();
309
      return data[boxes[0].first].prio;
310
     }
311

	
312
    /// \brief Deletes the item with minimum priority.
313
    ///
314
    /// This method deletes the item with minimum priority.
315
    /// \pre The heap must be non-empty.
316
    void pop() {
317
      moveDown();
318
      int index = boxes[0].first;
319
      iim[data[index].item] = POST_HEAP;
320
      remove(index);
321
      relocate_last(index);
322
    }
323

	
324
    /// \brief Deletes \c i from the heap.
325
    ///
326
    /// This method deletes item \c i from the heap, if \c i was
327
    /// already stored in the heap.
328
    /// \param i The item to erase.
329
    void erase(const Item &i) {
330
      int index = iim[i];
331
      iim[i] = POST_HEAP;
332
      remove(index);
333
      relocate_last(index);
334
   }
335

	
336
    /// \brief Returns the priority of \c i.
337
    ///
338
    /// This function returns the priority of item \c i.
339
    /// \pre \c i must be in the heap.
340
    /// \param i The item.
341
    Prio operator[](const Item &i) const {
342
      int idx = iim[i];
343
      return data[idx].prio;
344
    }
345

	
346
    /// \brief \c i gets to the heap with priority \c p independently
347
    /// if \c i was already there.
348
    ///
349
    /// This method calls \ref push(\c i, \c p) if \c i is not stored
350
    /// in the heap and sets the priority of \c i to \c p otherwise.
351
    /// It may throw an \e UnderFlowPriorityException.
352
    /// \param i The item.
353
    /// \param p The priority.
354
    void set(const Item &i, const Prio &p) {
355
      int idx = iim[i];
356
      if( idx < 0 ) {
357
        push(i, p);
358
      }
359
      else if( p >= data[idx].prio ) {
360
        data[idx].prio = p;
361
        bubble_up(idx);
362
      } else {
363
        data[idx].prio = p;
364
        bubble_down(idx);
365
      }
366
    }
367

	
368

	
369
    /// \brief Decreases the priority of \c i to \c p.
370
    ///
371
    /// This method decreases the priority of item \c i to \c p.
372
    /// \pre \c i must be stored in the heap with priority at least \c p, and
373
    /// \c should be greater or equal to the last removed item's priority.
374
    /// \param i The item.
375
    /// \param p The priority.
376
    void decrease(const Item &i, const Prio &p) {
377
      int idx = iim[i];
378
      data[idx].prio = p;
379
      bubble_down(idx);
380
    }
381

	
382
    /// \brief Increases the priority of \c i to \c p.
383
    ///
384
    /// This method sets the priority of item \c i to \c p.
385
    /// \pre \c i must be stored in the heap with priority at most \c p
386
    /// \param i The item.
387
    /// \param p The priority.
388
    void increase(const Item &i, const Prio &p) {
389
      int idx = iim[i];
390
      data[idx].prio = p;
391
      bubble_up(idx);
392
    }
393

	
394
    /// \brief Returns if \c item is in, has already been in, or has
395
    /// never been in the heap.
396
    ///
397
    /// This method returns PRE_HEAP if \c item has never been in the
398
    /// heap, IN_HEAP if it is in the heap at the moment, and POST_HEAP
399
    /// otherwise. In the latter case it is possible that \c item will
400
    /// get back to the heap again.
401
    /// \param i The item.
402
    State state(const Item &i) const {
403
      int s = iim[i];
404
      if( s >= 0 ) s = 0;
405
      return State(s);
406
    }
407

	
408
    /// \brief Sets the state of the \c item in the heap.
409
    ///
410
    /// Sets the state of the \c item in the heap. It can be used to
411
    /// manually clear the heap when it is important to achive the
412
    /// better time complexity.
413
    /// \param i The item.
414
    /// \param st The state. It should not be \c IN_HEAP.
415
    void state(const Item& i, State st) {
416
      switch (st) {
417
      case POST_HEAP:
418
      case PRE_HEAP:
419
        if (state(i) == IN_HEAP) {
420
          erase(i);
421
        }
422
        iim[i] = st;
423
        break;
424
      case IN_HEAP:
425
        break;
426
      }
427
    }
428

	
429
  }; // class RadixHeap
430

	
431
} // namespace lemon
432

	
433
#endif // LEMON_RADIX_HEAP_H
Show white space 4 line context
... ...
@@ -60,4 +60,5 @@
60 60
	lemon/bfs.h \
61 61
	lemon/bin_heap.h \
62
	lemon/bucket_heap.h \
62 63
	lemon/cbc.h \
63 64
	lemon/circulation.h \
... ...
@@ -77,4 +78,5 @@
77 78
	lemon/error.h \
78 79
	lemon/euler.h \
80
	lemon/fib_heap.h \
79 81
	lemon/full_graph.h \
80 82
	lemon/glpk.h \
... ...
@@ -100,4 +102,5 @@
100 102
	lemon/path.h \
101 103
	lemon/preflow.h \
104
	lemon/radix_heap.h \
102 105
	lemon/radix_sort.h \
103 106
	lemon/random.h \
Show white space 4 line context
... ...
@@ -32,4 +32,7 @@
32 32

	
33 33
#include <lemon/bin_heap.h>
34
#include <lemon/fib_heap.h>
35
#include <lemon/radix_heap.h>
36
#include <lemon/bucket_heap.h>
34 37

	
35 38
#include "test_tools.h"
... ...
@@ -184,4 +187,38 @@
184 187
  }
185 188

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

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

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

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

	
211
  {
212
    typedef BucketHeap<ItemIntMap> IntHeap;
213
    checkConcept<Heap<Prio, ItemIntMap>, IntHeap>();
214
    heapSortTest<IntHeap>();
215
    heapIncreaseTest<IntHeap>();
216

	
217
    typedef BucketHeap<IntNodeMap > NodeHeap;
218
    checkConcept<Heap<Prio, IntNodeMap >, NodeHeap>();
219
    dijkstraHeapTest<NodeHeap>(digraph, length, source);
220
  }
221

	
222

	
186 223
  return 0;
187 224
}
0 comments (0 inline)