gravatar
deba@inf.elte.hu
deba@inf.elte.hu
Unification of names in heaps (#50)
0 4 0
default
4 files changed with 297 insertions and 294 deletions:
↑ Collapse diff ↑
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
#ifndef LEMON_BIN_HEAP_H
20 20
#define LEMON_BIN_HEAP_H
21 21

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

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

	
30 30
namespace lemon {
31 31

	
32 32
  ///\ingroup auxdat
33 33
  ///
34 34
  ///\brief A Binary Heap implementation.
35 35
  ///
36
  ///This class implements the \e binary \e heap data structure. 
37
  /// 
36
  ///This class implements the \e binary \e heap data structure.
37
  ///
38 38
  ///A \e heap is a data structure for storing items with specified values
39 39
  ///called \e priorities in such a way that finding the item with minimum
40
  ///priority is efficient. \c Comp specifies the ordering of the priorities.
40
  ///priority is efficient. \c CMP specifies the ordering of the priorities.
41 41
  ///In a heap one can change the priority of an item, add or erase an
42 42
  ///item, etc.
43 43
  ///
44 44
  ///\tparam PR Type of the priority of the items.
45 45
  ///\tparam IM A read and writable item map with int values, used internally
46 46
  ///to handle the cross references.
47
  ///\tparam Comp A functor class for the ordering of the priorities.
47
  ///\tparam CMP A functor class for the ordering of the priorities.
48 48
  ///The default is \c std::less<PR>.
49 49
  ///
50 50
  ///\sa FibHeap
51 51
  ///\sa Dijkstra
52
  template <typename PR, typename IM, typename Comp = std::less<PR> >
52
  template <typename PR, typename IM, typename CMP = std::less<PR> >
53 53
  class BinHeap {
54 54

	
55 55
  public:
56 56
    ///\e
57 57
    typedef IM ItemIntMap;
58 58
    ///\e
59 59
    typedef PR Prio;
60 60
    ///\e
61 61
    typedef typename ItemIntMap::Key Item;
62 62
    ///\e
63 63
    typedef std::pair<Item,Prio> Pair;
64 64
    ///\e
65
    typedef Comp Compare;
65
    typedef CMP Compare;
66 66

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

	
81 81
  private:
82 82
    std::vector<Pair> _data;
83 83
    Compare _comp;
84 84
    ItemIntMap &_iim;
85 85

	
86 86
  public:
87 87
    /// \brief The constructor.
88 88
    ///
89 89
    /// The constructor.
90 90
    /// \param map should be given to the constructor, since it is used
91 91
    /// internally to handle the cross references. The value of the map
92 92
    /// must be \c PRE_HEAP (<tt>-1</tt>) for every item.
93 93
    explicit BinHeap(ItemIntMap &map) : _iim(map) {}
94 94

	
95 95
    /// \brief The constructor.
96 96
    ///
97 97
    /// The constructor.
98 98
    /// \param map should be given to the constructor, since it is used
99 99
    /// internally to handle the cross references. The value of the map
100 100
    /// should be PRE_HEAP (-1) for each element.
101 101
    ///
102 102
    /// \param comp The comparator function object.
103 103
    BinHeap(ItemIntMap &map, const Compare &comp)
104 104
      : _iim(map), _comp(comp) {}
105 105

	
106 106

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

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

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

	
127 127
  private:
128 128
    static int parent(int i) { return (i-1)/2; }
129 129

	
130 130
    static int second_child(int i) { return 2*i+2; }
131 131
    bool less(const Pair &p1, const Pair &p2) const {
132 132
      return _comp(p1.second, p2.second);
133 133
    }
134 134

	
135 135
    int bubble_up(int hole, Pair p) {
136 136
      int par = parent(hole);
137 137
      while( hole>0 && less(p,_data[par]) ) {
138 138
        move(_data[par],hole);
139 139
        hole = par;
140 140
        par = parent(hole);
141 141
      }
142 142
      move(p, hole);
143 143
      return hole;
144 144
    }
145 145

	
146 146
    int bubble_down(int hole, Pair p, int length) {
147 147
      int child = second_child(hole);
148 148
      while(child < length) {
149 149
        if( less(_data[child-1], _data[child]) ) {
150 150
          --child;
151 151
        }
152 152
        if( !less(_data[child], p) )
153 153
          goto ok;
154 154
        move(_data[child], hole);
155 155
        hole = child;
156 156
        child = second_child(hole);
157 157
      }
158 158
      child--;
159 159
      if( child<length && less(_data[child], p) ) {
160 160
        move(_data[child], hole);
161 161
        hole=child;
Ignore white space 192 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
#ifndef LEMON_BUCKET_HEAP_H
20 20
#define LEMON_BUCKET_HEAP_H
21 21

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

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

	
30 30
namespace lemon {
31 31

	
32 32
  namespace _bucket_heap_bits {
33 33

	
34
    template <bool minimize>
34
    template <bool MIN>
35 35
    struct DirectionTraits {
36 36
      static bool less(int left, int right) {
37 37
        return left < right;
38 38
      }
39 39
      static void increase(int& value) {
40 40
        ++value;
41 41
      }
42 42
    };
43 43

	
44 44
    template <>
45 45
    struct DirectionTraits<false> {
46 46
      static bool less(int left, int right) {
47 47
        return left > right;
48 48
      }
49 49
      static void increase(int& value) {
50 50
        --value;
51 51
      }
52 52
    };
53 53

	
54 54
  }
55 55

	
56 56
  /// \ingroup auxdat
57 57
  ///
58 58
  /// \brief A Bucket Heap implementation.
59 59
  ///
60 60
  /// This class implements the \e bucket \e heap data structure. A \e heap
61 61
  /// is a data structure for storing items with specified values called \e
62 62
  /// priorities in such a way that finding the item with minimum priority is
63 63
  /// efficient. The bucket heap is very simple implementation, it can store
64 64
  /// only integer priorities and it stores for each priority in the
65 65
  /// \f$ [0..C) \f$ range a list of items. So it should be used only when
66 66
  /// the priorities are small. It is not intended to use as dijkstra heap.
67 67
  ///
68
  /// \param _ItemIntMap A read and writable Item int map, used internally
68
  /// \param IM A read and write Item int map, used internally
69 69
  /// to handle the cross references.
70
  /// \param minimize If the given parameter is true then the heap gives back
71
  /// the lowest priority.
72
  template <typename _ItemIntMap, bool minimize = true>
70
  /// \param MIN If the given parameter is false then instead of the
71
  /// minimum value the maximum can be retrivied with the top() and
72
  /// prio() member functions.
73
  template <typename IM, bool MIN = true>
73 74
  class BucketHeap {
74 75

	
75 76
  public:
76 77
    /// \e
77
    typedef typename _ItemIntMap::Key Item;
78
    typedef typename IM::Key Item;
78 79
    /// \e
79 80
    typedef int Prio;
80 81
    /// \e
81 82
    typedef std::pair<Item, Prio> Pair;
82 83
    /// \e
83
    typedef _ItemIntMap ItemIntMap;
84
    typedef IM ItemIntMap;
84 85

	
85 86
  private:
86 87

	
87
    typedef _bucket_heap_bits::DirectionTraits<minimize> Direction;
88
    typedef _bucket_heap_bits::DirectionTraits<MIN> Direction;
88 89

	
89 90
  public:
90 91

	
91 92
    /// \brief Type to represent the items states.
92 93
    ///
93 94
    /// Each Item element have a state associated to it. It may be "in heap",
94 95
    /// "pre heap" or "post heap". The latter two are indifferent from the
95 96
    /// heap's point of view, but may be useful to the user.
96 97
    ///
97
    /// The ItemIntMap \e should be initialized in such way that it maps
98
    /// PRE_HEAP (-1) to any element to be put in the heap...
98
    /// The item-int map must be initialized in such way that it assigns
99
    /// \c PRE_HEAP (<tt>-1</tt>) to any element to be put in the heap.
99 100
    enum State {
100
      IN_HEAP = 0,
101
      PRE_HEAP = -1,
102
      POST_HEAP = -2
101
      IN_HEAP = 0,    ///< = 0.
102
      PRE_HEAP = -1,  ///< = -1.
103
      POST_HEAP = -2  ///< = -2.
103 104
    };
104 105

	
105 106
  public:
106 107
    /// \brief The constructor.
107 108
    ///
108 109
    /// The constructor.
109
    /// \param _index should be given to the constructor, since it is used
110
    /// \param map should be given to the constructor, since it is used
110 111
    /// internally to handle the cross references. The value of the map
111 112
    /// should be PRE_HEAP (-1) for each element.
112
    explicit BucketHeap(ItemIntMap &_index) : index(_index), minimal(0) {}
113
    explicit BucketHeap(ItemIntMap &map) : _iim(map), _minimum(0) {}
113 114

	
114 115
    /// The number of items stored in the heap.
115 116
    ///
116 117
    /// \brief Returns the number of items stored in the heap.
117
    int size() const { return data.size(); }
118
    int size() const { return _data.size(); }
118 119

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

	
124 125
    /// \brief Make empty this heap.
125 126
    ///
126 127
    /// Make empty this heap. It does not change the cross reference
127 128
    /// map.  If you want to reuse a heap what is not surely empty you
128 129
    /// should first clear the heap and after that you should set the
129 130
    /// cross reference map for each item to \c PRE_HEAP.
130 131
    void clear() {
131
      data.clear(); first.clear(); minimal = 0;
132
      _data.clear(); _first.clear(); _minimum = 0;
132 133
    }
133 134

	
134 135
  private:
135 136

	
136 137
    void relocate_last(int idx) {
137
      if (idx + 1 < int(data.size())) {
138
        data[idx] = data.back();
139
        if (data[idx].prev != -1) {
140
          data[data[idx].prev].next = idx;
138
      if (idx + 1 < int(_data.size())) {
139
        _data[idx] = _data.back();
140
        if (_data[idx].prev != -1) {
141
          _data[_data[idx].prev].next = idx;
141 142
        } else {
142
          first[data[idx].value] = idx;
143
          _first[_data[idx].value] = idx;
143 144
        }
144
        if (data[idx].next != -1) {
145
          data[data[idx].next].prev = idx;
145
        if (_data[idx].next != -1) {
146
          _data[_data[idx].next].prev = idx;
146 147
        }
147
        index[data[idx].item] = idx;
148
        _iim[_data[idx].item] = idx;
148 149
      }
149
      data.pop_back();
150
      _data.pop_back();
150 151
    }
151 152

	
152 153
    void unlace(int idx) {
153
      if (data[idx].prev != -1) {
154
        data[data[idx].prev].next = data[idx].next;
154
      if (_data[idx].prev != -1) {
155
        _data[_data[idx].prev].next = _data[idx].next;
155 156
      } else {
156
        first[data[idx].value] = data[idx].next;
157
        _first[_data[idx].value] = _data[idx].next;
157 158
      }
158
      if (data[idx].next != -1) {
159
        data[data[idx].next].prev = data[idx].prev;
159
      if (_data[idx].next != -1) {
160
        _data[_data[idx].next].prev = _data[idx].prev;
160 161
      }
161 162
    }
162 163

	
163 164
    void lace(int idx) {
164
      if (int(first.size()) <= data[idx].value) {
165
        first.resize(data[idx].value + 1, -1);
165
      if (int(_first.size()) <= _data[idx].value) {
166
        _first.resize(_data[idx].value + 1, -1);
166 167
      }
167
      data[idx].next = first[data[idx].value];
168
      if (data[idx].next != -1) {
169
        data[data[idx].next].prev = idx;
168
      _data[idx].next = _first[_data[idx].value];
169
      if (_data[idx].next != -1) {
170
        _data[_data[idx].next].prev = idx;
170 171
      }
171
      first[data[idx].value] = idx;
172
      data[idx].prev = -1;
172
      _first[_data[idx].value] = idx;
173
      _data[idx].prev = -1;
173 174
    }
174 175

	
175 176
  public:
176 177
    /// \brief Insert a pair of item and priority into the heap.
177 178
    ///
178 179
    /// Adds \c p.first to the heap with priority \c p.second.
179 180
    /// \param p The pair to insert.
180 181
    void push(const Pair& p) {
181 182
      push(p.first, p.second);
182 183
    }
183 184

	
184 185
    /// \brief Insert an item into the heap with the given priority.
185 186
    ///
186 187
    /// Adds \c i to the heap with priority \c p.
187 188
    /// \param i The item to insert.
188 189
    /// \param p The priority of the item.
189 190
    void push(const Item &i, const Prio &p) {
190
      int idx = data.size();
191
      index[i] = idx;
192
      data.push_back(BucketItem(i, p));
191
      int idx = _data.size();
192
      _iim[i] = idx;
193
      _data.push_back(BucketItem(i, p));
193 194
      lace(idx);
194
      if (Direction::less(p, minimal)) {
195
        minimal = p;
195
      if (Direction::less(p, _minimum)) {
196
        _minimum = p;
196 197
      }
197 198
    }
198 199

	
199 200
    /// \brief Returns the item with minimum priority.
200 201
    ///
201 202
    /// This method returns the item with minimum priority.
202 203
    /// \pre The heap must be nonempty.
203 204
    Item top() const {
204
      while (first[minimal] == -1) {
205
        Direction::increase(minimal);
205
      while (_first[_minimum] == -1) {
206
        Direction::increase(_minimum);
206 207
      }
207
      return data[first[minimal]].item;
208
      return _data[_first[_minimum]].item;
208 209
    }
209 210

	
210 211
    /// \brief Returns the minimum priority.
211 212
    ///
212 213
    /// It returns the minimum priority.
213 214
    /// \pre The heap must be nonempty.
214 215
    Prio prio() const {
215
      while (first[minimal] == -1) {
216
        Direction::increase(minimal);
216
      while (_first[_minimum] == -1) {
217
        Direction::increase(_minimum);
217 218
      }
218
      return minimal;
219
      return _minimum;
219 220
    }
220 221

	
221 222
    /// \brief Deletes the item with minimum priority.
222 223
    ///
223 224
    /// This method deletes the item with minimum priority from the heap.
224 225
    /// \pre The heap must be non-empty.
225 226
    void pop() {
226
      while (first[minimal] == -1) {
227
        Direction::increase(minimal);
227
      while (_first[_minimum] == -1) {
228
        Direction::increase(_minimum);
228 229
      }
229
      int idx = first[minimal];
230
      index[data[idx].item] = -2;
230
      int idx = _first[_minimum];
231
      _iim[_data[idx].item] = -2;
231 232
      unlace(idx);
232 233
      relocate_last(idx);
233 234
    }
234 235

	
235 236
    /// \brief Deletes \c i from the heap.
236 237
    ///
237 238
    /// This method deletes item \c i from the heap, if \c i was
238 239
    /// already stored in the heap.
239 240
    /// \param i The item to erase.
240 241
    void erase(const Item &i) {
241
      int idx = index[i];
242
      index[data[idx].item] = -2;
242
      int idx = _iim[i];
243
      _iim[_data[idx].item] = -2;
243 244
      unlace(idx);
244 245
      relocate_last(idx);
245 246
    }
246 247

	
247 248

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

	
258 259
    /// \brief \c i gets to the heap with priority \c p independently
259 260
    /// if \c i was already there.
260 261
    ///
261 262
    /// This method calls \ref push(\c i, \c p) if \c i is not stored
262 263
    /// in the heap and sets the priority of \c i to \c p otherwise.
263 264
    /// \param i The item.
264 265
    /// \param p The priority.
265 266
    void set(const Item &i, const Prio &p) {
266
      int idx = index[i];
267
      int idx = _iim[i];
267 268
      if (idx < 0) {
268 269
        push(i, p);
269
      } else if (Direction::less(p, data[idx].value)) {
270
      } else if (Direction::less(p, _data[idx].value)) {
270 271
        decrease(i, p);
271 272
      } else {
272 273
        increase(i, p);
273 274
      }
274 275
    }
275 276

	
276 277
    /// \brief Decreases the priority of \c i to \c p.
277 278
    ///
278 279
    /// This method decreases the priority of item \c i to \c p.
279 280
    /// \pre \c i must be stored in the heap with priority at least \c
280 281
    /// p relative to \c Compare.
281 282
    /// \param i The item.
282 283
    /// \param p The priority.
283 284
    void decrease(const Item &i, const Prio &p) {
284
      int idx = index[i];
285
      int idx = _iim[i];
285 286
      unlace(idx);
286
      data[idx].value = p;
287
      if (Direction::less(p, minimal)) {
288
        minimal = p;
287
      _data[idx].value = p;
288
      if (Direction::less(p, _minimum)) {
289
        _minimum = p;
289 290
      }
290 291
      lace(idx);
291 292
    }
292 293

	
293 294
    /// \brief Increases the priority of \c i to \c p.
294 295
    ///
295 296
    /// This method sets the priority of item \c i to \c p.
296 297
    /// \pre \c i must be stored in the heap with priority at most \c
297 298
    /// p relative to \c Compare.
298 299
    /// \param i The item.
299 300
    /// \param p The priority.
300 301
    void increase(const Item &i, const Prio &p) {
301
      int idx = index[i];
302
      int idx = _iim[i];
302 303
      unlace(idx);
303
      data[idx].value = p;
304
      _data[idx].value = p;
304 305
      lace(idx);
305 306
    }
306 307

	
307 308
    /// \brief Returns if \c item is in, has already been in, or has
308 309
    /// never been in the heap.
309 310
    ///
310 311
    /// This method returns PRE_HEAP if \c item has never been in the
311 312
    /// heap, IN_HEAP if it is in the heap at the moment, and POST_HEAP
312 313
    /// otherwise. In the latter case it is possible that \c item will
313 314
    /// get back to the heap again.
314 315
    /// \param i The item.
315 316
    State state(const Item &i) const {
316
      int idx = index[i];
317
      int idx = _iim[i];
317 318
      if (idx >= 0) idx = 0;
318 319
      return State(idx);
319 320
    }
320 321

	
321 322
    /// \brief Sets the state of the \c item in the heap.
322 323
    ///
323 324
    /// Sets the state of the \c item in the heap. It can be used to
324 325
    /// manually clear the heap when it is important to achive the
325 326
    /// better time complexity.
326 327
    /// \param i The item.
327 328
    /// \param st The state. It should not be \c IN_HEAP.
328 329
    void state(const Item& i, State st) {
329 330
      switch (st) {
330 331
      case POST_HEAP:
331 332
      case PRE_HEAP:
332 333
        if (state(i) == IN_HEAP) {
333 334
          erase(i);
334 335
        }
335
        index[i] = st;
336
        _iim[i] = st;
336 337
        break;
337 338
      case IN_HEAP:
338 339
        break;
339 340
      }
340 341
    }
341 342

	
342 343
  private:
343 344

	
344 345
    struct BucketItem {
345 346
      BucketItem(const Item& _item, int _value)
346 347
        : item(_item), value(_value) {}
347 348

	
348 349
      Item item;
349 350
      int value;
350 351

	
351 352
      int prev, next;
352 353
    };
353 354

	
354
    ItemIntMap& index;
355
    std::vector<int> first;
356
    std::vector<BucketItem> data;
357
    mutable int minimal;
355
    ItemIntMap& _iim;
356
    std::vector<int> _first;
357
    std::vector<BucketItem> _data;
358
    mutable int _minimum;
358 359

	
359 360
  }; // class BucketHeap
360 361

	
361 362
  /// \ingroup auxdat
362 363
  ///
363 364
  /// \brief A Simplified Bucket Heap implementation.
364 365
  ///
365 366
  /// This class implements a simplified \e bucket \e heap data
366 367
  /// structure.  It does not provide some functionality but it faster
367 368
  /// and simplier data structure than the BucketHeap. The main
368 369
  /// difference is that the BucketHeap stores for every key a double
369 370
  /// linked list while this class stores just simple lists. In the
370 371
  /// other way it does not support erasing each elements just the
371 372
  /// minimal and it does not supports key increasing, decreasing.
372 373
  ///
373
  /// \param _ItemIntMap A read and writable Item int map, used internally
374
  /// \param IM A read and write Item int map, used internally
374 375
  /// to handle the cross references.
375
  /// \param minimize If the given parameter is true then the heap gives back
376
  /// the lowest priority.
376
  /// \param MIN If the given parameter is false then instead of the
377
  /// minimum value the maximum can be retrivied with the top() and
378
  /// prio() member functions.
377 379
  ///
378 380
  /// \sa BucketHeap
379
  template <typename _ItemIntMap, bool minimize = true >
381
  template <typename IM, bool MIN = true >
380 382
  class SimpleBucketHeap {
381 383

	
382 384
  public:
383
    typedef typename _ItemIntMap::Key Item;
385
    typedef typename IM::Key Item;
384 386
    typedef int Prio;
385 387
    typedef std::pair<Item, Prio> Pair;
386
    typedef _ItemIntMap ItemIntMap;
388
    typedef IM ItemIntMap;
387 389

	
388 390
  private:
389 391

	
390
    typedef _bucket_heap_bits::DirectionTraits<minimize> Direction;
392
    typedef _bucket_heap_bits::DirectionTraits<MIN> Direction;
391 393

	
392 394
  public:
393 395

	
394 396
    /// \brief Type to represent the items states.
395 397
    ///
396 398
    /// Each Item element have a state associated to it. It may be "in heap",
397 399
    /// "pre heap" or "post heap". The latter two are indifferent from the
398 400
    /// heap's point of view, but may be useful to the user.
399 401
    ///
400
    /// The ItemIntMap \e should be initialized in such way that it maps
401
    /// PRE_HEAP (-1) to any element to be put in the heap...
402
    /// The item-int map must be initialized in such way that it assigns
403
    /// \c PRE_HEAP (<tt>-1</tt>) to any element to be put in the heap.
402 404
    enum State {
403
      IN_HEAP = 0,
404
      PRE_HEAP = -1,
405
      POST_HEAP = -2
405
      IN_HEAP = 0,    ///< = 0.
406
      PRE_HEAP = -1,  ///< = -1.
407
      POST_HEAP = -2  ///< = -2.
406 408
    };
407 409

	
408 410
  public:
409 411

	
410 412
    /// \brief The constructor.
411 413
    ///
412 414
    /// The constructor.
413
    /// \param _index should be given to the constructor, since it is used
415
    /// \param map should be given to the constructor, since it is used
414 416
    /// internally to handle the cross references. The value of the map
415 417
    /// should be PRE_HEAP (-1) for each element.
416
    explicit SimpleBucketHeap(ItemIntMap &_index)
417
      : index(_index), free(-1), num(0), minimal(0) {}
418
    explicit SimpleBucketHeap(ItemIntMap &map)
419
      : _iim(map), _free(-1), _num(0), _minimum(0) {}
418 420

	
419 421
    /// \brief Returns the number of items stored in the heap.
420 422
    ///
421 423
    /// The number of items stored in the heap.
422
    int size() const { return num; }
424
    int size() const { return _num; }
423 425

	
424 426
    /// \brief Checks if the heap stores no items.
425 427
    ///
426 428
    /// Returns \c true if and only if the heap stores no items.
427
    bool empty() const { return num == 0; }
429
    bool empty() const { return _num == 0; }
428 430

	
429 431
    /// \brief Make empty this heap.
430 432
    ///
431 433
    /// Make empty this heap. It does not change the cross reference
432 434
    /// map.  If you want to reuse a heap what is not surely empty you
433 435
    /// should first clear the heap and after that you should set the
434 436
    /// cross reference map for each item to \c PRE_HEAP.
435 437
    void clear() {
436
      data.clear(); first.clear(); free = -1; num = 0; minimal = 0;
438
      _data.clear(); _first.clear(); _free = -1; _num = 0; _minimum = 0;
437 439
    }
438 440

	
439 441
    /// \brief Insert a pair of item and priority into the heap.
440 442
    ///
441 443
    /// Adds \c p.first to the heap with priority \c p.second.
442 444
    /// \param p The pair to insert.
443 445
    void push(const Pair& p) {
444 446
      push(p.first, p.second);
445 447
    }
446 448

	
447 449
    /// \brief Insert an item into the heap with the given priority.
448 450
    ///
449 451
    /// Adds \c i to the heap with priority \c p.
450 452
    /// \param i The item to insert.
451 453
    /// \param p The priority of the item.
452 454
    void push(const Item &i, const Prio &p) {
453 455
      int idx;
454
      if (free == -1) {
455
        idx = data.size();
456
        data.push_back(BucketItem(i));
456
      if (_free == -1) {
457
        idx = _data.size();
458
        _data.push_back(BucketItem(i));
457 459
      } else {
458
        idx = free;
459
        free = data[idx].next;
460
        data[idx].item = i;
460
        idx = _free;
461
        _free = _data[idx].next;
462
        _data[idx].item = i;
461 463
      }
462
      index[i] = idx;
463
      if (p >= int(first.size())) first.resize(p + 1, -1);
464
      data[idx].next = first[p];
465
      first[p] = idx;
466
      if (Direction::less(p, minimal)) {
467
        minimal = p;
464
      _iim[i] = idx;
465
      if (p >= int(_first.size())) _first.resize(p + 1, -1);
466
      _data[idx].next = _first[p];
467
      _first[p] = idx;
468
      if (Direction::less(p, _minimum)) {
469
        _minimum = p;
468 470
      }
469
      ++num;
471
      ++_num;
470 472
    }
471 473

	
472 474
    /// \brief Returns the item with minimum priority.
473 475
    ///
474 476
    /// This method returns the item with minimum priority.
475 477
    /// \pre The heap must be nonempty.
476 478
    Item top() const {
477
      while (first[minimal] == -1) {
478
        Direction::increase(minimal);
479
      while (_first[_minimum] == -1) {
480
        Direction::increase(_minimum);
479 481
      }
480
      return data[first[minimal]].item;
482
      return _data[_first[_minimum]].item;
481 483
    }
482 484

	
483 485
    /// \brief Returns the minimum priority.
484 486
    ///
485 487
    /// It returns the minimum priority.
486 488
    /// \pre The heap must be nonempty.
487 489
    Prio prio() const {
488
      while (first[minimal] == -1) {
489
        Direction::increase(minimal);
490
      while (_first[_minimum] == -1) {
491
        Direction::increase(_minimum);
490 492
      }
491
      return minimal;
493
      return _minimum;
492 494
    }
493 495

	
494 496
    /// \brief Deletes the item with minimum priority.
495 497
    ///
496 498
    /// This method deletes the item with minimum priority from the heap.
497 499
    /// \pre The heap must be non-empty.
498 500
    void pop() {
499
      while (first[minimal] == -1) {
500
        Direction::increase(minimal);
501
      while (_first[_minimum] == -1) {
502
        Direction::increase(_minimum);
501 503
      }
502
      int idx = first[minimal];
503
      index[data[idx].item] = -2;
504
      first[minimal] = data[idx].next;
505
      data[idx].next = free;
506
      free = idx;
507
      --num;
504
      int idx = _first[_minimum];
505
      _iim[_data[idx].item] = -2;
506
      _first[_minimum] = _data[idx].next;
507
      _data[idx].next = _free;
508
      _free = idx;
509
      --_num;
508 510
    }
509 511

	
510 512
    /// \brief Returns the priority of \c i.
511 513
    ///
512 514
    /// This function returns the priority of item \c i.
513 515
    /// \warning This operator is not a constant time function
514 516
    /// because it scans the whole data structure to find the proper
515 517
    /// value.
516 518
    /// \pre \c i must be in the heap.
517 519
    /// \param i The item.
518 520
    Prio operator[](const Item &i) const {
519
      for (int k = 0; k < first.size(); ++k) {
520
        int idx = first[k];
521
      for (int k = 0; k < _first.size(); ++k) {
522
        int idx = _first[k];
521 523
        while (idx != -1) {
522
          if (data[idx].item == i) {
524
          if (_data[idx].item == i) {
523 525
            return k;
524 526
          }
525
          idx = data[idx].next;
527
          idx = _data[idx].next;
526 528
        }
527 529
      }
528 530
      return -1;
529 531
    }
530 532

	
531 533
    /// \brief Returns if \c item is in, has already been in, or has
532 534
    /// never been in the heap.
533 535
    ///
534 536
    /// This method returns PRE_HEAP if \c item has never been in the
535 537
    /// heap, IN_HEAP if it is in the heap at the moment, and POST_HEAP
536 538
    /// otherwise. In the latter case it is possible that \c item will
537 539
    /// get back to the heap again.
538 540
    /// \param i The item.
539 541
    State state(const Item &i) const {
540
      int idx = index[i];
542
      int idx = _iim[i];
541 543
      if (idx >= 0) idx = 0;
542 544
      return State(idx);
543 545
    }
544 546

	
545 547
  private:
546 548

	
547 549
    struct BucketItem {
548 550
      BucketItem(const Item& _item)
549 551
        : item(_item) {}
550 552

	
551 553
      Item item;
552 554
      int next;
553 555
    };
554 556

	
555
    ItemIntMap& index;
556
    std::vector<int> first;
557
    std::vector<BucketItem> data;
558
    int free, num;
559
    mutable int minimal;
557
    ItemIntMap& _iim;
558
    std::vector<int> _first;
559
    std::vector<BucketItem> _data;
560
    int _free, _num;
561
    mutable int _minimum;
560 562

	
561 563
  }; // class SimpleBucketHeap
562 564

	
563 565
}
564 566

	
565 567
#endif
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
#ifndef LEMON_FIB_HEAP_H
20 20
#define LEMON_FIB_HEAP_H
21 21

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

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

	
30 30
namespace lemon {
31 31

	
32 32
  /// \ingroup auxdat
33 33
  ///
34 34
  ///\brief Fibonacci Heap.
35 35
  ///
36 36
  ///This class implements the \e Fibonacci \e heap data structure. A \e heap
37 37
  ///is a data structure for storing items with specified values called \e
38 38
  ///priorities in such a way that finding the item with minimum priority is
39
  ///efficient. \c Compare specifies the ordering of the priorities. In a heap
39
  ///efficient. \c CMP specifies the ordering of the priorities. In a heap
40 40
  ///one can change the priority of an item, add or erase an item, etc.
41 41
  ///
42 42
  ///The methods \ref increase and \ref erase are not efficient in a Fibonacci
43 43
  ///heap. In case of many calls to these operations, it is better to use a
44 44
  ///\ref BinHeap "binary heap".
45 45
  ///
46
  ///\param _Prio Type of the priority of the items.
47
  ///\param _ItemIntMap A read and writable Item int map, used internally
46
  ///\param PRIO Type of the priority of the items.
47
  ///\param IM A read and writable Item int map, used internally
48 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>.
49
  ///\param CMP A class for the ordering of the priorities. The
50
  ///default is \c std::less<PRIO>.
51 51
  ///
52 52
  ///\sa BinHeap
53 53
  ///\sa Dijkstra
54 54
#ifdef DOXYGEN
55
  template <typename _Prio,
56
            typename _ItemIntMap,
57
            typename _Compare>
55
  template <typename PRIO, typename IM, typename CMP>
58 56
#else
59
  template <typename _Prio,
60
            typename _ItemIntMap,
61
            typename _Compare = std::less<_Prio> >
57
  template <typename PRIO, typename IM, typename CMP = std::less<PRIO> >
62 58
#endif
63 59
  class FibHeap {
64 60
  public:
65 61
    ///\e
66
    typedef _ItemIntMap ItemIntMap;
62
    typedef IM ItemIntMap;
67 63
    ///\e
68
    typedef _Prio Prio;
64
    typedef PRIO Prio;
69 65
    ///\e
70 66
    typedef typename ItemIntMap::Key Item;
71 67
    ///\e
72 68
    typedef std::pair<Item,Prio> Pair;
73 69
    ///\e
74
    typedef _Compare Compare;
70
    typedef CMP Compare;
75 71

	
76 72
  private:
77
    class store;
73
    class Store;
78 74

	
79
    std::vector<store> container;
80
    int minimum;
81
    ItemIntMap &iimap;
82
    Compare comp;
83
    int num_items;
75
    std::vector<Store> _data;
76
    int _minimum;
77
    ItemIntMap &_iim;
78
    Compare _comp;
79
    int _num;
84 80

	
85 81
  public:
86
    ///Status of the nodes
82

	
83
    /// \brief Type to represent the items states.
84
    ///
85
    /// Each Item element have a state associated to it. It may be "in heap",
86
    /// "pre heap" or "post heap". The latter two are indifferent from the
87
    /// heap's point of view, but may be useful to the user.
88
    ///
89
    /// The item-int map must be initialized in such way that it assigns
90
    /// \c PRE_HEAP (<tt>-1</tt>) to any element to be put in the heap.
87 91
    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
92
      IN_HEAP = 0,    ///< = 0.
93
      PRE_HEAP = -1,  ///< = -1.
94
      POST_HEAP = -2  ///< = -2.
94 95
    };
95 96

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

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

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

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

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

	
131 132
    /// \brief \c item gets to the heap with priority \c value independently
132 133
    /// if \c item was already there.
133 134
    ///
134 135
    /// This method calls \ref push(\c item, \c value) if \c item is not
135 136
    /// stored in the heap and it calls \ref decrease(\c item, \c value) or
136 137
    /// \ref increase(\c item, \c value) otherwise.
137 138
    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);
139
      int i=_iim[item];
140
      if ( i >= 0 && _data[i].in ) {
141
        if ( _comp(value, _data[i].prio) ) decrease(item, value);
142
        if ( _comp(_data[i].prio, value) ) increase(item, value);
142 143
      } else push(item, value);
143 144
    }
144 145

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

	
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;
166
      if ( _num ) {
167
        _data[_data[_minimum].right_neighbor].left_neighbor=i;
168
        _data[i].right_neighbor=_data[_minimum].right_neighbor;
169
        _data[_minimum].right_neighbor=i;
170
        _data[i].left_neighbor=_minimum;
171
        if ( _comp( value, _data[_minimum].prio) ) _minimum=i;
171 172
      } else {
172
        container[i].right_neighbor=container[i].left_neighbor=i;
173
        minimum=i;
173
        _data[i].right_neighbor=_data[i].left_neighbor=i;
174
        _minimum=i;
174 175
      }
175
      container[i].prio=value;
176
      ++num_items;
176
      _data[i].prio=value;
177
      ++_num;
177 178
    }
178 179

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

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

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

	
200 201
    /// \brief Deletes the item with minimum priority relative to \c Compare.
201 202
    ///
202 203
    /// This method deletes the item with minimum priority relative to \c
203 204
    /// Compare from the heap.
204 205
    /// \pre The heap must be non-empty.
205 206
    void pop() {
206 207
      /*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;
208
      if ( _data[_minimum].left_neighbor==_minimum ) {
209
        _data[_minimum].in=false;
210
        if ( _data[_minimum].degree!=0 ) {
211
          makeroot(_data[_minimum].child);
212
          _minimum=_data[_minimum].child;
212 213
          balance();
213 214
        }
214 215
      } 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;
216
        int right=_data[_minimum].right_neighbor;
217
        unlace(_minimum);
218
        _data[_minimum].in=false;
219
        if ( _data[_minimum].degree > 0 ) {
220
          int left=_data[_minimum].left_neighbor;
221
          int child=_data[_minimum].child;
222
          int last_child=_data[child].left_neighbor;
222 223

	
223 224
          makeroot(child);
224 225

	
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;
226
          _data[left].right_neighbor=child;
227
          _data[child].left_neighbor=left;
228
          _data[right].left_neighbor=last_child;
229
          _data[last_child].right_neighbor=right;
229 230
        }
230
        minimum=right;
231
        _minimum=right;
231 232
        balance();
232 233
      } // the case where there are more roots
233
      --num_items;
234
      --_num;
234 235
    }
235 236

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

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

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

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

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

	
283 284

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

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

	
321 322
  private:
322 323

	
323 324
    void balance() {
324 325

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

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

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

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

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

	
356 357

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

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

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

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

	
388 389

	
389 390
      /*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;
391
      int right=_data[_minimum].right_neighbor;
392
      _data[_minimum].right_neighbor=a;
393
      _data[a].left_neighbor=_minimum;
394
      _data[a].right_neighbor=right;
395
      _data[right].left_neighbor=a;
395 396

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

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

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

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

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

	
418
      if (container[a].degree==0) {
419
        container[b].left_neighbor=b;
420
        container[b].right_neighbor=b;
421
        container[a].child=b;
419
      if (_data[a].degree==0) {
420
        _data[b].left_neighbor=b;
421
        _data[b].right_neighbor=b;
422
        _data[a].child=b;
422 423
      } 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;
424
        int child=_data[a].child;
425
        int last_child=_data[child].left_neighbor;
426
        _data[child].left_neighbor=b;
427
        _data[b].right_neighbor=child;
428
        _data[last_child].right_neighbor=b;
429
        _data[b].left_neighbor=last_child;
429 430
      }
430 431

	
431
      ++container[a].degree;
432
      ++_data[a].degree;
432 433

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

	
436 437
    /*
437 438
     *It is invoked only if a has siblings.
438 439
     */
439 440
    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;
441
      int leftn=_data[a].left_neighbor;
442
      int rightn=_data[a].right_neighbor;
443
      _data[leftn].right_neighbor=rightn;
444
      _data[rightn].left_neighbor=leftn;
444 445
    }
445 446

	
446 447

	
447
    class store {
448
    class Store {
448 449
      friend class FibHeap;
449 450

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

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

	
464 465
} //namespace lemon
465 466

	
466 467
#endif //LEMON_FIB_HEAP_H
467 468

	
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
#ifndef LEMON_RADIX_HEAP_H
20 20
#define LEMON_RADIX_HEAP_H
21 21

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

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

	
29 29
namespace lemon {
30 30

	
31 31

	
32 32
  /// \ingroup auxdata
33 33
  ///
34 34
  /// \brief A Radix Heap implementation.
35 35
  ///
36 36
  /// This class implements the \e radix \e heap data structure. A \e heap
37 37
  /// is a data structure for storing items with specified values called \e
38 38
  /// priorities in such a way that finding the item with minimum priority is
39 39
  /// efficient. This heap type can store only items with \e int priority.
40 40
  /// In a heap one can change the priority of an item, add or erase an
41 41
  /// item, but the priority cannot be decreased under the last removed
42 42
  /// item's priority.
43 43
  ///
44
  /// \param _ItemIntMap A read and writable Item int map, used internally
44
  /// \param IM A read and writable Item int map, used internally
45 45
  /// to handle the cross references.
46 46
  ///
47 47
  /// \see BinHeap
48 48
  /// \see Dijkstra
49
  template <typename _ItemIntMap>
49
  template <typename IM>
50 50
  class RadixHeap {
51 51

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

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

	
63 63
    class UnderFlowPriorityError : public Exception {
64 64
    public:
65 65
      virtual const char* what() const throw() {
66 66
        return "lemon::RadixHeap::UnderFlowPriorityError";
67 67
      }
68 68
    };
69 69

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

	
84 84
  private:
85 85

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

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

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

	
102
    ItemIntMap &iim;
102
    ItemIntMap &_iim;
103 103

	
104 104

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

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

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

	
149 149
  private:
150 150

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

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

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

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

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

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

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

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

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

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

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

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

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

	
276 276
  public:
277 277

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

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

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

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

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

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

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

	
368 368

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

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

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

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

	
429 429
  }; // class RadixHeap
430 430

	
431 431
} // namespace lemon
432 432

	
433 433
#endif // LEMON_RADIX_HEAP_H
0 comments (0 inline)