aGrUM  0.20.3
a C++ library for (probabilistic) graphical models
heap.h
Go to the documentation of this file.
1 /**
2  *
3  * Copyright (c) 2005-2021 by Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
4  * info_at_agrum_dot_org
5  *
6  * This library is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this library. If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 
22 /**
23  * @file
24  * @brief Heaps definition.
25  *
26  * @author Christophe GONZALES(@AMU) and Pierre-Henri WUILLEMIN(@LIP6)
27  *
28  */
29 
30 #ifndef GUM_HEAP_H
31 #define GUM_HEAP_H
32 
33 #include <functional>
34 #include <initializer_list>
35 #include <utility>
36 #include <vector>
37 
38 #include <agrum/agrum.h>
39 
40 namespace gum {
41 
42 #define GUM_HEAP_DEFAULT_CAPACITY 10
43 
44  // templates provided by this file
45 
46  template < typename Val, typename Cmp, typename Alloc >
47  class Heap;
48  template < typename Val, typename Cmp, typename Alloc >
49  std::ostream& operator<<(std::ostream&, const Heap< Val, Cmp, Alloc >&);
50 
51  // ===========================================================================
52  // === SIMPLE HEAP DATA STRUCTURE ===
53  // ===========================================================================
54 
55  /**
56  * @class Heap
57  * @headerfile heap.h <agrum/tools/core/heap.h>
58  * @brief Heap data structure
59  * @ingroup basicstruct_group
60  * @ingroup heap_group
61  *
62  * This structure is a basic heap data structure, i.e., it is a container in
63  * which elements are sorted according to a weak ordering. Given this
64  * ordering, we do have access in O(1) to the "smallest" element contained by
65  * the structure. Insertions and deletions of elements are processed in O(ln
66  * n), where n is the number of elements in the heap. In addition to the
67  * classical pop, top and push functions, Heap provide direct accessors to
68  * the elements in the heap (see operator[]). However, these can only be
69  * accessed in read-only mode.
70  * @par Usage example:
71  * @code
72  * // create a heap of integers, the top element is the smallest element
73  * Heap<int> heap1;
74  *
75  * // create a heap of floats, the top element is the greatest
76  * Heap<float> heap2 (std::greater<float>());
77  *
78  * // insert elements into the heap
79  * heap1.insert (8);
80  * heap1.insert (10);
81  * heap1.insert (2);
82  * heap1.insert (23);
83  * heap1.insert (24);
84  * heap1.insert (10);
85  * heap1.insert (10);
86  *
87  * // copy a heap into another
88  * Heap<int> heap2 = heap1;
89  *
90  * // get the number of elements of the heap
91  * std::cerr << heap2.size() << std::endl;
92  *
93  * // get the top element but do not remove it
94  * std::cerr << heap2.top() << std::endl;
95  *
96  * // get and remove the top element of the heap
97  * std::cerr << heap2.pop() << std::endl;
98  *
99  * // remove the top element but do not return it (faster than above)
100  * heap2.eraseTop();
101  *
102  * // erase in heap1 value 8
103  * heap1.eraseByVal (8);
104  *
105  * // erase element at position 3 (see function erase for the
106  * // meaning of position 3)
107  * heap1.erase (3);
108  *
109  * // get the element at position 3
110  * heap1[3];
111  *
112  * // check whether element 24 belongs to the heap
113  * heap1.contains (24);
114  * @endcode
115  *
116  * @tparam Val The gum::Heap values type.
117  * @tparam Cmp The comperator used to sort elements in the gum::Heap.
118  * @tparam Alloc The allocator of elements stored in the gum::Heap.
119  */
120  template < typename Val, typename Cmp = std::less< Val >, typename Alloc = std::allocator< Val > >
121  class Heap {
122  public:
123  /// Types for STL compliance
124  /// @{
125  using value_type = Val;
126  using reference = Val&;
127  using const_reference = const Val&;
128  using pointer = Val*;
129  using const_pointer = const Val*;
130  using size_type = std::size_t;
131  using difference_type = std::ptrdiff_t;
132  using allocator_type = Alloc;
133  /// @}
134 
135  // ============================================================================
136  /// @name Constructors / Destructors
137  // ============================================================================
138  /// @{
139 
140  /**
141  * @brief Basic constructor: creates an empty heap.
142  * @param compare a function taking two elements in argument, say e1 and
143  * e2, and returning a Boolean indicating wether e1 < e2, i.e., whether e1
144  * should be nearer than e2 to the top of the heap.
145  * @param capacity the size of the internal data structures containing the
146  * elements (could be for instance vectors or hashtables).
147  */
148  explicit Heap(Cmp compare = Cmp(), Size capacity = GUM_HEAP_DEFAULT_CAPACITY);
149 
150  /**
151  * @brief Initializer list constructor.
152  * @param list The initializer list.
153  */
154  explicit Heap(std::initializer_list< Val > list);
155 
156  /**
157  * @brief Copy constructor.
158  * @param from The gum::Heap to copy.
159  */
160  Heap(const Heap< Val, Cmp, Alloc >& from);
161 
162  /**
163  * @brief Generalized copy constructor.
164  * @tparam OtherAlloc The other gum::Heap allocator.
165  * @param from The gum::Heap to copy.
166  */
167  template < typename OtherAlloc >
168  Heap(const Heap< Val, Cmp, OtherAlloc >& from);
169 
170  /**
171  * @brief Move constructor.
172  * @param from The gum::Heap to move.
173  */
174  Heap(Heap< Val, Cmp, Alloc >&& from) noexcept;
175 
176  /**
177  * @brief Class destructor.
178  */
179  ~Heap();
180 
181  /// @}
182  // ============================================================================
183  /// @name Operators
184  // ============================================================================
185  /// @{
186 
187  /**
188  * @brief Copy operator.
189  *
190  * When a problem occurs during the copy (for instance when not enough
191  * memory is available), the operator guarantees that the heap stays in a
192  * coherent state. Actually, the heap becomes empty. An exception is then
193  * thrown.
194  *
195  * @param from The gum::Heap to copy.
196  */
197  Heap< Val, Cmp, Alloc >& operator=(const Heap< Val, Cmp, Alloc >& from);
198 
199  /**
200  * @brief Generalized copy operator.
201  *
202  * When a problem occurs during the copy (for instance when not enough
203  * memory is available), the operator guarantees that the heap stays in a
204  * coherent state. Actually, the heap becomes empty. An exception is then
205  * thrown.
206  *
207  * @tparam OtherAlloc The other gum::Heap allocator.
208  * @param from The gum::Heap to copy.
209  */
210  template < typename OtherAlloc >
211  Heap< Val, Cmp, Alloc >& operator=(const Heap< Val, Cmp, OtherAlloc >& from);
212 
213  /**
214  * @brief Move operator.
215  *
216  * When a problem occurs during the copy (for instance when not enough
217  * memory is available), the operator guarantees that the heap stays in a
218  * coherent state. Actually, the heap becomes empty. An exception is then
219  * thrown.
220  *
221  * @param from The gum::Heap to move.
222  */
223  Heap< Val, Cmp, Alloc >& operator=(Heap< Val, Cmp, Alloc >&& from) noexcept;
224 
225  /**
226  * @brief Returns the element at index index_elt from the heap.
227  *
228  * @param index_elt The index of the element to return.
229  * @return Returns the element at index index_elt from the heap.
230  * @throw NotFound exception is thrown if there is no element
231  * at position "index_elt".
232  */
233  const Val& operator[](Size index_elt) const;
234 
235  /// @}
236  // ============================================================================
237  /// @name Accessors / Modifiers
238  // ============================================================================
239  /// @{
240 
241  /**
242  * @brief Returns the element at the top of the heap.
243  * @return Returns the element at the top of the heap.
244  * @throw NotFound exception is thrown if the heap is empty.
245  */
246  const Val& top() const;
247 
248  /**
249  * @brief Removes the top element from the heap and return it.
250  * @return Returns the top element from the heap.
251  * @throw NotFound exception is thrown if the heap is empty.
252  */
253  Val pop();
254 
255  /**
256  * @brief Removes the top of the heap (but does not return it).
257  *
258  * If the heap is empty, it does nothing (in particular, it does not throw
259  * any exception).
260  */
261  void eraseTop();
262 
263  /**
264  * @brief Removes the element positioned at "index" from the heap.
265  *
266  * If the element cannot be found, the function returns without throwing
267  * any exception. @param index represents the position of the element to
268  * be removed. This is computed as follows: suppose that the heap is a
269  * complete binary tree, that is, a binary tree where all levels are
270  * completely filled except, maybe, the last one and, in this case, the
271  * elements of this level are all to the left of the tree. Then parsing the
272  * tree from top to bottom and, for each level, from left to right, and
273  * assigning index 0 to the root of the tree and, incrementing the index by
274  * 1 each time we jump to another node, we get a unique index for each
275  * element. This is precisely what the index passed in argument of the
276  * function represents.
277  *
278  * @param index The index of the element to remove
279  */
280  void eraseByPos(Size index);
281 
282  /**
283  * @brief Removes a given element from the heap (but does not return it).
284  *
285  * If the element cannot be found, the function returns without throwing
286  * any exception.
287  *
288  * @param val The element we wish to remove. If the heap contains several
289  * times this element, then the one with the smallest index is removed.
290  */
291  void erase(const Val& val);
292 
293  /**
294  * @brief inserts a new element (actually a copy) in the heap and returns
295  * its index
296  *
297  * @param val The element to insert.
298  * @return The inserted element position in the gum::Heap.
299  */
300  Size insert(const Val& val);
301 
302  /**
303  * @brief Inserts a new element (by moving it) in the heap and returns its
304  * index.
305  *
306  * @param val The element to insert.
307  * @return The inserted element position in the gum::Heap.
308  */
309  Size insert(Val&& val);
310 
311  /**
312  * @brief Emplace a new element in the heap and returns its index.
313  *
314  * @tparam Args the type of the new element to emplace.
315  * @param args The new element to emplace.
316  * @return The emplaced element position in the gum::Heap.
317  */
318  template < typename... Args >
319  Size emplace(Args&&... args);
320 
321  /**
322  * @brief Returns the number of elements in the heap.
323  * @return Returns the number of elements in the heap.
324  */
325  Size size() const noexcept;
326 
327  /**
328  * @brief Indicates whether the heap is empty.
329  * @return Indicates whether the heap is empty.
330  */
331  bool empty() const noexcept;
332 
333  /**
334  * @brief Indicates whether the heap contains a given value.
335  * @return Indicates whether the heap contains a given value.
336  */
337  bool contains(const Val&) const;
338 
339  /**
340  * @return Displays the content of the heap.
341  * @return Returns a std::string representing the content of the heap.
342  */
343  std::string toString() const;
344 
345  /// @}
346  // ============================================================================
347  /// @name Fine tuning
348  // ============================================================================
349  /// @{
350 
351  /**
352  * @brief Returns the size of the internal structure storing the heap.
353  * @return Returns the size of the internal structure storing the heap.
354  */
355  Size capacity() const noexcept;
356 
357  /**
358  * @brief Changes the size of the the internal structure storing the heap.
359  *
360  * If the new size does not enable the heap to contain the elements it
361  * currently contains, then the resizing does not occur.
362  *
363  * @param new_size The gum::Heap new size.
364  */
365  void resize(Size new_size);
366 
367  /// @}
368 
369  private:
370  /// An array storing all the elements of the heap.
371  std::vector< Val, Alloc > _heap_;
372 
373  /// The number of elements in the heap.
375 
376  /// Comparison function.
377  Cmp _cmp_;
378 
379  /// After inserting an element at the end of the heap, restore heap property
381  };
382 
383 } /* namespace gum */
384 
385 
386 #ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
387 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
388 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
389 extern template class gum::Heap< int >;
390 # endif
391 # endif
392 #endif
393 #ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
394 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
395 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
396 extern template class gum::Heap< long >;
397 # endif
398 # endif
399 #endif
400 
401 #ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
402 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
403 # ifndef GUM_NO_EXTERN_TEMPLATE_CLASS
404 extern template class gum::Heap< double >;
405 # endif
406 # endif
407 #endif
408 
409 
410 // always include the implementation of the templates
411 #include <agrum/tools/core/heap_tpl.h>
412 
413 #endif /* GUM_HEAP_H */
bool contains(const Val &) const
Indicates whether the heap contains a given value.
Definition: heap_tpl.h:299
Heap(Heap< Val, Cmp, Alloc > &&from) noexcept
Move constructor.
Definition: heap_tpl.h:80
Heap(std::initializer_list< Val > list)
Initializer list constructor.
Definition: heap_tpl.h:46
bool empty() const noexcept
Indicates whether the heap is empty.
Definition: heap_tpl.h:293
Heap(Cmp compare=Cmp(), Size capacity=GUM_HEAP_DEFAULT_CAPACITY)
Basic constructor: creates an empty heap.
Definition: heap_tpl.h:38
std::vector< Val, Alloc > _heap_
An array storing all the elements of the heap.
Definition: heap.h:371
#define GUM_HEAP_DEFAULT_CAPACITY
Definition: heap.h:42
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:643
const Val & operator[](Size index_elt) const
Returns the element at index index_elt from the heap.
Definition: heap_tpl.h:308
Val pop()
Removes the top element from the heap and return it.
Definition: heap_tpl.h:239
Size _nb_elements_
The number of elements in the heap.
Definition: heap.h:374
Size emplace(Args &&... args)
Emplace a new element in the heap and returns its index.
Definition: heap_tpl.h:284
~Heap()
Class destructor.
Definition: heap_tpl.h:89
Size _restoreHeap_()
After inserting an element at the end of the heap, restore heap property.
Definition: heap_tpl.h:249
void erase(const Val &val)
Removes a given element from the heap (but does not return it).
Definition: heap_tpl.h:220
std::string toString() const
Definition: heap_tpl.h:317
Size size() const noexcept
Returns the number of elements in the heap.
Definition: heap_tpl.h:174
Heap< Val, Cmp, Alloc > & operator=(Heap< Val, Cmp, Alloc > &&from) noexcept
Move operator.
Definition: heap_tpl.h:153
Heap< Val, Cmp, Alloc > & operator=(const Heap< Val, Cmp, OtherAlloc > &from)
Generalized copy operator.
Definition: heap_tpl.h:123
Size insert(const Val &val)
inserts a new element (actually a copy) in the heap and returns its index
Definition: heap_tpl.h:265
Size insert(Val &&val)
Inserts a new element (by moving it) in the heap and returns its index.
Definition: heap_tpl.h:274
void eraseTop()
Removes the top of the heap (but does not return it).
Definition: heap_tpl.h:231
Heap(const Heap< Val, Cmp, Alloc > &from)
Copy constructor.
Definition: heap_tpl.h:57
Heap< Val, Cmp, Alloc > & operator=(const Heap< Val, Cmp, Alloc > &from)
Copy operator.
Definition: heap_tpl.h:96
Size capacity() const noexcept
Returns the size of the internal structure storing the heap.
Definition: heap_tpl.h:180
void resize(Size new_size)
Changes the size of the the internal structure storing the heap.
Definition: heap_tpl.h:186
void eraseByPos(Size index)
Removes the element positioned at "index" from the heap.
Definition: heap_tpl.h:192
Heap(const Heap< Val, Cmp, OtherAlloc > &from)
Generalized copy constructor.
Definition: heap_tpl.h:66
Cmp _cmp_
Comparison function.
Definition: heap.h:377
const Val & top() const
Returns the element at the top of the heap.
Definition: heap_tpl.h:166