COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/linear_heap.h @ 1955:daca31868d70

Last change on this file since 1955:daca31868d70 was 1906:7fa90b66ca9e, checked in by Balazs Dezso, 18 years ago

Omitting warnings

File size: 12.9 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    /// \brief Sets the state of the \c item in the heap.
287    ///
288    /// Sets the state of the \c item in the heap. It can be used to
289    /// manually clear the heap when it is important to achive the
290    /// better time complexity.
291    /// \param i The item.
292    /// \param st The state. It should not be \c IN_HEAP.
293    void state(const Item& i, state_enum st) {
294      switch (st) {
295      case POST_HEAP:
296      case PRE_HEAP:
297        if (state(i) == IN_HEAP) {
298          erase(i);
299        }
300        index[i] = st;
301        break;
302      case IN_HEAP:
303        break;
304      }
305    }
306
307  private:
308
309    struct LinearItem {
310      LinearItem(const Item& _item, int _value)
311        : item(_item), value(_value) {}
312
313      Item item;
314      int value;
315
316      int prev, next;
317    };
318
319    ItemIntMap& index;
320    std::vector<int> first;
321    std::vector<LinearItem> data;
322    mutable int minimal;
323
324  }; // class LinearHeap
325
326
327  template <typename _Item, typename _ItemIntMap>
328  class LinearHeap<_Item, _ItemIntMap, false> {
329
330  public:
331    typedef _Item Item;
332    typedef int Prio;
333    typedef std::pair<Item, Prio> Pair;
334    typedef _ItemIntMap ItemIntMap;
335
336    enum state_enum {
337      IN_HEAP = 0,
338      PRE_HEAP = -1,
339      POST_HEAP = -2
340    };
341
342  public:
343
344    explicit LinearHeap(ItemIntMap &_index) : index(_index), maximal(-1) {}
345
346    int size() const { return data.size(); }
347    bool empty() const { return data.empty(); }
348
349    void clear() {
350      for (int i = 0; i < (int)data.size(); ++i) {
351        index[data[i].item] = -2;
352      }
353      data.clear(); first.clear(); maximal = -1;
354    }
355
356  private:
357
358    void relocate_last(int idx) {
359      if (idx + 1 != (int)data.size()) {
360        data[idx] = data.back();
361        if (data[idx].prev != -1) {
362          data[data[idx].prev].next = idx;
363        } else {
364          first[data[idx].value] = idx;
365        }
366        if (data[idx].next != -1) {
367          data[data[idx].next].prev = idx;
368        }
369        index[data[idx].item] = idx;
370      }
371      data.pop_back();
372    }
373
374    void unlace(int idx) {
375      if (data[idx].prev != -1) {
376        data[data[idx].prev].next = data[idx].next;
377      } else {
378        first[data[idx].value] = data[idx].next;
379      }
380      if (data[idx].next != -1) {
381        data[data[idx].next].prev = data[idx].prev;
382      }
383    }
384
385    void lace(int idx) {
386      if ((int)first.size() <= data[idx].value) {
387        first.resize(data[idx].value + 1, -1);
388      }
389      data[idx].next = first[data[idx].value];
390      if (data[idx].next != -1) {
391        data[data[idx].next].prev = idx;
392      }
393      first[data[idx].value] = idx;
394      data[idx].prev = -1;
395    }
396
397  public:
398
399    void push(const Pair& p) {
400      push(p.first, p.second);
401    }
402
403    void push(const Item &i, const Prio &p) {
404      int idx = data.size();
405      index[i] = idx;
406      data.push_back(LinearItem(i, p));
407      lace(idx);
408      if (data[idx].value > maximal) {
409        maximal = data[idx].value;
410      }
411    }
412
413    Item top() const {
414      while (first[maximal] == -1) {
415        --maximal;
416      }
417      return data[first[maximal]].item;
418    }
419
420    Prio prio() const {
421      while (first[maximal] == -1) {
422        --maximal;
423      }
424      return maximal;
425    }
426
427    void pop() {
428      while (first[maximal] == -1) {
429        --maximal;
430      }
431      int idx = first[maximal];
432      index[data[idx].item] = -2;
433      unlace(idx);
434      relocate_last(idx);
435    }
436
437    void erase(const Item &i) {
438      int idx = index[i];
439      index[data[idx].item] = -2;
440      unlace(idx);
441      relocate_last(idx);
442    }
443
444    Prio operator[](const Item &i) const {
445      int idx = index[i];
446      return data[idx].value;
447    }
448
449    void set(const Item &i, const Prio &p) {
450      int idx = index[i];
451      if (idx < 0) {
452        push(i,p);
453      } else if (p > data[idx].value) {
454        decrease(i, p);
455      } else {
456        increase(i, p);
457      }
458    }
459
460    void decrease(const Item &i, const Prio &p) {
461      int idx = index[i];
462      unlace(idx);
463      data[idx].value = p;
464      if (p > maximal) {
465        maximal = p;
466      }
467      lace(idx);
468    }
469   
470    void increase(const Item &i, const Prio &p) {
471      int idx = index[i];
472      unlace(idx);
473      data[idx].value = p;
474      lace(idx);
475    }
476
477    state_enum state(const Item &i) const {
478      int idx = index[i];
479      if (idx >= 0) idx = 0;
480      return state_enum(idx);
481    }
482
483    void state(const Item& i, state_enum st) {
484      switch (st) {
485      case POST_HEAP:
486      case PRE_HEAP:
487        if (state(i) == IN_HEAP) {
488          erase(i);
489        }
490        index[i] = st;
491        break;
492      case IN_HEAP:
493        break;
494      }
495    }
496
497  private:
498
499    struct LinearItem {
500      LinearItem(const Item& _item, int _value)
501        : item(_item), value(_value) {}
502
503      Item item;
504      int value;
505
506      int prev, next;
507    };
508
509    ItemIntMap& index;
510    std::vector<int> first;
511    std::vector<LinearItem> data;
512    mutable int maximal;
513
514  }; // class LinearHeap
515
516}
517 
518#endif
Note: See TracBrowser for help on using the repository browser.