COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/linear_heap.h @ 1875:98698b69a902

Last change on this file since 1875:98698b69a902 was 1875:98698b69a902, checked in by Alpar Juttner, 19 years ago

Happy new year to LEMON

File size: 12.1 KB
Line 
1/* -*- C++ -*-
2 * lemon/linear_heap.h - Part of LEMON, a generic C++ optimization library
3 *
4 * Copyright (C) 2006 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
5 * (Egervary Research Group on Combinatorial Optimization, EGRES).
6 *
7 * Permission to use, modify and distribute this software is granted
8 * provided that this copyright notice appears in all copies. For
9 * precise terms see the accompanying LICENSE file.
10 *
11 * This software is provided "AS IS" with no warranty of any kind,
12 * express or implied, and with no claim as to its suitability for any
13 * purpose.
14 *
15 */
16
17#ifndef LEMON_LINEAR_HEAP_H
18#define LEMON_LINEAR_HEAP_H
19
20///\ingroup auxdat
21///\file
22///\brief Binary Heap implementation.
23
24#include <vector>
25#include <utility>
26#include <functional>
27
28namespace lemon {
29
30  /// \ingroup auxdat
31
32  /// \brief A Linear Heap implementation.
33  ///
34  /// This class implements the \e linear \e heap data structure. A \e heap
35  /// is a data structure for storing items with specified values called \e
36  /// priorities in such a way that finding the item with minimum priority is
37  /// efficient. The linear heap is very simple implementation, it can store
38  /// only integer priorities and it stores for each priority in the [0..C]
39  /// range a list of items. So it should be used only when the priorities
40  /// are small. It is not intended to use as dijkstra heap.
41  ///
42  /// \param _Item Type of the items to be stored. 
43  /// \param _ItemIntMap A read and writable Item int map, used internally
44  /// to handle the cross references.
45  /// \param minimize If the given parameter is true then the heap gives back
46  /// the lowest priority.
47  template <typename _Item, typename _ItemIntMap, bool minimize = true >
48  class LinearHeap {
49
50  public:
51    typedef _Item Item;
52    typedef int Prio;
53    typedef std::pair<Item, Prio> Pair;
54    typedef _ItemIntMap ItemIntMap;
55
56    /// \brief Type to represent the items states.
57    ///
58    /// Each Item element have a state associated to it. It may be "in heap",
59    /// "pre heap" or "post heap". The latter two are indifferent from the
60    /// heap's point of view, but may be useful to the user.
61    ///
62    /// The ItemIntMap \e should be initialized in such way that it maps
63    /// PRE_HEAP (-1) to any element to be put in the heap...
64    enum state_enum {
65      IN_HEAP = 0,
66      PRE_HEAP = -1,
67      POST_HEAP = -2
68    };
69
70  public:
71    /// \brief The constructor.
72    ///
73    /// The constructor.
74    /// \param _index should be given to the constructor, since it is used
75    /// internally to handle the cross references. The value of the map
76    /// should be PRE_HEAP (-1) for each element.
77    explicit LinearHeap(ItemIntMap &_index) : index(_index), minimal(0) {}
78   
79    /// The number of items stored in the heap.
80    ///
81    /// \brief Returns the number of items stored in the heap.
82    int size() const { return data.size(); }
83   
84    /// \brief Checks if the heap stores no items.
85    ///
86    /// Returns \c true if and only if the heap stores no items.
87    bool empty() const { return data.empty(); }
88
89    /// \brief Make empty this heap.
90    ///
91    /// Make empty this heap.
92    void clear() {
93      for (int i = 0; i < (int)data.size(); ++i) {
94        index[data[i].item] = -2;
95      }
96      data.clear(); first.clear(); minimal = 0;
97    }
98
99  private:
100
101    void relocate_last(int idx) {
102      if (idx + 1 < (int)data.size()) {
103        data[idx] = data.back();
104        if (data[idx].prev != -1) {
105          data[data[idx].prev].next = idx;
106        } else {
107          first[data[idx].value] = idx;
108        }
109        if (data[idx].next != -1) {
110          data[data[idx].next].prev = idx;
111        }
112        index[data[idx].item] = idx;
113      }
114      data.pop_back();
115    }
116
117    void unlace(int idx) {
118      if (data[idx].prev != -1) {
119        data[data[idx].prev].next = data[idx].next;
120      } else {
121        first[data[idx].value] = data[idx].next;
122      }
123      if (data[idx].next != -1) {
124        data[data[idx].next].prev = data[idx].prev;
125      }
126    }
127
128    void lace(int idx) {
129      if ((int)first.size() <= data[idx].value) {
130        first.resize(data[idx].value + 1, -1);
131      }
132      data[idx].next = first[data[idx].value];
133      if (data[idx].next != -1) {
134        data[data[idx].next].prev = idx;
135      }
136      first[data[idx].value] = idx;
137      data[idx].prev = -1;
138    }
139
140  public:
141    /// \brief Insert a pair of item and priority into the heap.
142    ///
143    /// Adds \c p.first to the heap with priority \c p.second.
144    /// \param p The pair to insert.
145    void push(const Pair& p) {
146      push(p.first, p.second);
147    }
148
149    /// \brief Insert an item into the heap with the given priority.
150    ///   
151    /// Adds \c i to the heap with priority \c p.
152    /// \param i The item to insert.
153    /// \param p The priority of the item.
154    void push(const Item &i, const Prio &p) {
155      int idx = data.size();
156      index[i] = idx;
157      data.push_back(LinearItem(i, p));
158      lace(idx);
159      if (p < minimal) {
160        minimal = p;
161      }
162    }
163
164    /// \brief Returns the item with minimum priority.
165    ///
166    /// This method returns the item with minimum priority.
167    /// \pre The heap must be nonempty. 
168    Item top() const {
169      while (first[minimal] == -1) {
170        ++minimal;
171      }
172      return data[first[minimal]].item;
173    }
174
175    /// \brief Returns the minimum priority.
176    ///
177    /// It returns the minimum priority.
178    /// \pre The heap must be nonempty.
179    Prio prio() const {
180      while (first[minimal] == -1) {
181        ++minimal;
182      }
183      return minimal;
184    }
185
186    /// \brief Deletes the item with minimum priority.
187    ///
188    /// This method deletes the item with minimum priority from the heap. 
189    /// \pre The heap must be non-empty. 
190    void pop() {
191      while (first[minimal] == -1) {
192        ++minimal;
193      }
194      int idx = first[minimal];
195      index[data[idx].item] = -2;
196      unlace(idx);
197      relocate_last(idx);
198    }
199
200    /// \brief Deletes \c i from the heap.
201    ///
202    /// This method deletes item \c i from the heap, if \c i was
203    /// already stored in the heap.
204    /// \param i The item to erase.
205    void erase(const Item &i) {
206      int idx = index[i];
207      index[data[idx].item] = -2;
208      unlace(idx);
209      relocate_last(idx);
210    }
211
212   
213    /// \brief Returns the priority of \c i.
214    ///
215    /// This function returns the priority of item \c i. 
216    /// \pre \c i must be in the heap.
217    /// \param i The item.
218    Prio operator[](const Item &i) const {
219      int idx = index[i];
220      return data[idx].value;
221    }
222
223    /// \brief \c i gets to the heap with priority \c p independently
224    /// if \c i was already there.
225    ///
226    /// This method calls \ref push(\c i, \c p) if \c i is not stored
227    /// in the heap and sets the priority of \c i to \c p otherwise.
228    /// \param i The item.
229    /// \param p The priority.
230    void set(const Item &i, const Prio &p) {
231      int idx = index[i];
232      if (idx < 0) {
233        push(i,p);
234      } else if (p > data[idx].value) {
235        increase(i, p);
236      } else {
237        decrease(i, p);
238      }
239    }
240
241    /// \brief Decreases the priority of \c i to \c p.
242
243    /// This method decreases the priority of item \c i to \c p.
244    /// \pre \c i must be stored in the heap with priority at least \c
245    /// p relative to \c Compare.
246    /// \param i The item.
247    /// \param p The priority.
248    void decrease(const Item &i, const Prio &p) {
249      int idx = index[i];
250      unlace(idx);
251      data[idx].value = p;
252      if (p < minimal) {
253        minimal = p;
254      }
255      lace(idx);
256    }
257   
258    /// \brief Increases the priority of \c i to \c p.
259    ///
260    /// This method sets the priority of item \c i to \c p.
261    /// \pre \c i must be stored in the heap with priority at most \c
262    /// p relative to \c Compare.
263    /// \param i The item.
264    /// \param p The priority.
265    void increase(const Item &i, const Prio &p) {
266      int idx = index[i];
267      unlace(idx);
268      data[idx].value = p;
269      lace(idx);
270    }
271
272    /// \brief Returns if \c item is in, has already been in, or has
273    /// never been in the heap.
274    ///
275    /// This method returns PRE_HEAP if \c item has never been in the
276    /// heap, IN_HEAP if it is in the heap at the moment, and POST_HEAP
277    /// otherwise. In the latter case it is possible that \c item will
278    /// get back to the heap again.
279    /// \param i The item.
280    state_enum state(const Item &i) const {
281      int idx = index[i];
282      if (idx >= 0) idx = 0;
283      return state_enum(idx);
284    }
285
286  private:
287
288    struct LinearItem {
289      LinearItem(const Item& _item, int _value)
290        : item(_item), value(_value) {}
291
292      Item item;
293      int value;
294
295      int prev, next;
296    };
297
298    ItemIntMap& index;
299    std::vector<int> first;
300    std::vector<LinearItem> data;
301    mutable int minimal;
302
303  }; // class LinearHeap
304
305
306  template <typename _Item, typename _ItemIntMap>
307  class LinearHeap<_Item, _ItemIntMap, false> {
308
309  public:
310    typedef _Item Item;
311    typedef int Prio;
312    typedef std::pair<Item, Prio> Pair;
313    typedef _ItemIntMap ItemIntMap;
314
315    enum state_enum {
316      IN_HEAP = 0,
317      PRE_HEAP = -1,
318      POST_HEAP = -2
319    };
320
321  public:
322
323    explicit LinearHeap(ItemIntMap &_index) : index(_index), maximal(-1) {}
324
325    int size() const { return data.size(); }
326    bool empty() const { return data.empty(); }
327
328    void clear() {
329      for (int i = 0; i < (int)data.size(); ++i) {
330        index[data[i].item] = -2;
331      }
332      data.clear(); first.clear(); maximal = -1;
333    }
334
335  private:
336
337    void relocate_last(int idx) {
338      if (idx + 1 != (int)data.size()) {
339        data[idx] = data.back();
340        if (data[idx].prev != -1) {
341          data[data[idx].prev].next = idx;
342        } else {
343          first[data[idx].value] = idx;
344        }
345        if (data[idx].next != -1) {
346          data[data[idx].next].prev = idx;
347        }
348        index[data[idx].item] = idx;
349      }
350      data.pop_back();
351    }
352
353    void unlace(int idx) {
354      if (data[idx].prev != -1) {
355        data[data[idx].prev].next = data[idx].next;
356      } else {
357        first[data[idx].value] = data[idx].next;
358      }
359      if (data[idx].next != -1) {
360        data[data[idx].next].prev = data[idx].prev;
361      }
362    }
363
364    void lace(int idx) {
365      if ((int)first.size() <= data[idx].value) {
366        first.resize(data[idx].value + 1, -1);
367      }
368      data[idx].next = first[data[idx].value];
369      if (data[idx].next != -1) {
370        data[data[idx].next].prev = idx;
371      }
372      first[data[idx].value] = idx;
373      data[idx].prev = -1;
374    }
375
376  public:
377
378    void push(const Pair& p) {
379      push(p.first, p.second);
380    }
381
382    void push(const Item &i, const Prio &p) {
383      int idx = data.size();
384      index[i] = idx;
385      data.push_back(LinearItem(i, p));
386      lace(idx);
387      if (data[idx].value > maximal) {
388        maximal = data[idx].value;
389      }
390    }
391
392    Item top() const {
393      while (first[maximal] == -1) {
394        --maximal;
395      }
396      return data[first[maximal]].item;
397    }
398
399    Prio prio() const {
400      while (first[maximal] == -1) {
401        --maximal;
402      }
403      return maximal;
404    }
405
406    void pop() {
407      while (first[maximal] == -1) {
408        --maximal;
409      }
410      int idx = first[maximal];
411      index[data[idx].item] = -2;
412      unlace(idx);
413      relocate_last(idx);
414    }
415
416    void erase(const Item &i) {
417      int idx = index[i];
418      index[data[idx].item] = -2;
419      unlace(idx);
420      relocate_last(idx);
421    }
422
423    Prio operator[](const Item &i) const {
424      int idx = index[i];
425      return data[idx].value;
426    }
427
428    void set(const Item &i, const Prio &p) {
429      int idx = index[i];
430      if (idx < 0) {
431        push(i,p);
432      } else if (p > data[idx].value) {
433        decrease(i, p);
434      } else {
435        increase(i, p);
436      }
437    }
438
439    void decrease(const Item &i, const Prio &p) {
440      int idx = index[i];
441      unlace(idx);
442      data[idx].value = p;
443      if (p > maximal) {
444        maximal = p;
445      }
446      lace(idx);
447    }
448   
449    void increase(const Item &i, const Prio &p) {
450      int idx = index[i];
451      unlace(idx);
452      data[idx].value = p;
453      lace(idx);
454    }
455
456    state_enum state(const Item &i) const {
457      int idx = index[i];
458      if (idx >= 0) idx = 0;
459      return state_enum(idx);
460    }
461
462  private:
463
464    struct LinearItem {
465      LinearItem(const Item& _item, int _value)
466        : item(_item), value(_value) {}
467
468      Item item;
469      int value;
470
471      int prev, next;
472    };
473
474    ItemIntMap& index;
475    std::vector<int> first;
476    std::vector<LinearItem> data;
477    mutable int maximal;
478
479  }; // class LinearHeap
480
481}
482 
483#endif
Note: See TracBrowser for help on using the repository browser.