Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
tpl_dynArrayHeap.H
Go to the documentation of this file.
1/*
2 Aleph_w
3
4 Data structures & Algorithms
5 version 2.0.0b
6 https://github.com/lrleon/Aleph-w
7
8 This file is part of Aleph-w library
9
10 Copyright (c) 2002-2026 Leandro Rabindranath Leon
11
12 Permission is hereby granted, free of charge, to any person obtaining a copy
13 of this software and associated documentation files (the "Software"), to deal
14 in the Software without restriction, including without limitation the rights
15 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 copies of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions:
18
19 The above copyright notice and this permission notice shall be included in all
20 copies or substantial portions of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 SOFTWARE.
29*/
30
31
49# ifndef TPL_DYNARRAYHEAP_H
50# define TPL_DYNARRAYHEAP_H
51
52# include <algorithm>
53# include <cstddef>
54# include <stdexcept>
55# include <utility>
56
57# include <tpl_dynArray.H>
58# include <ah-errors.H>
59
60namespace Aleph
61{
69 template <typename T, class Compare>
70 inline
71 size_t sift_up(DynArray<T> & a, const size_t l, const size_t r, Compare & cmp) noexcept
72 {
73 for (size_t p, i = r; i > l; i = p)
74 {
75 p = u_index(i); // parent index (p = i / 2)
76
77 // Prefetch grandparent for next iteration
78 if (const size_t gp = u_index(p); gp >= l)
79 __builtin_prefetch(&a.access(gp), 0, 1);
80
81 T & ap = a.access(p);
82 T & ai = a.access(i);
83 if (cmp(ap, ai)) [[likely]] // heap property holds
84 return i;
85
86 std::swap(ap, ai); // swap and continue at parent
87 }
88
89 return l;
90 }
91
97 template <typename T, class Compare>
98 inline
99 void sift_down(DynArray<T> & a, const size_t l, const size_t r, Compare & cmp) noexcept
100 {
101 size_t i = l;
102 while (true)
103 {
104 size_t c = l_index(i); // left child index (c = 2 * i)
105 if (c > r) [[unlikely]] // no left child
106 return;
107
108 // Prefetch grandchildren for next iteration
109 if (const size_t gc = l_index(c); gc <= r)
110 __builtin_prefetch(&a.access(gc), 0, 1);
111
112 T *ac = &a.access(c);
113 if (c + 1 <= r) // right child exists
114 {
115 T *ac1 = &a.access(c + 1);
116 if (cmp(*ac1, *ac)) // pick the child with higher priority
117 {
118 c++;
119 ac = ac1;
120 }
121 }
122
123 T & ai = a.access(i);
124 if (cmp(ai, *ac)) [[likely]] // heap property holds
125 return;
126
127 std::swap(*ac, ai);
128 i = c;
129 }
130 }
131
132
141 template <typename T, class Compare = Aleph::less<T>>
142 class DynArrayHeap : public LocateFunctions<DynArrayHeap<T, Compare>, T>,
143 public FunctionalMethods<DynArrayHeap<T, Compare>, T>,
144 public GenericKeys<DynArrayHeap<T, Compare>, T>,
145 public EqualToMethod<DynArrayHeap<T, Compare>>,
146 public StlAlephIterator<DynArrayHeap<T, Compare>>
147 {
149 size_t num_items = 0;
150
151 Compare cmp;
152
153 static size_t r_index(const size_t & i) noexcept
154 {
155 return (i << 1) + 1; // right child index
156 }
157
158 public:
159 using Item_Type = T;
160
162 DynArrayHeap(Compare cmp_fct = Compare()) : cmp(cmp_fct)
163 {
164 // empty
165 }
166
168
170
179 {
180 ah_underflow_error_if(num_items == 0) << "Heap is empty";
181
182 return array.access(1);
183 }
184
186 const T &top() const
187 {
188 ah_underflow_error_if(num_items == 0) << "Heap is empty";
189
190 return array.access(1);
191 }
192
201 T &insert(const T & key)
202 {
203 array.touch(++num_items) = key; // place new element
204 const size_t pos = sift_up(array, 1, num_items, cmp);
205 return array.access(pos);
206 }
207
213 T &insert(T && key)
214 {
215 array.touch(++num_items) = std::move(key); // place new element
216 const size_t pos = sift_up(array, 1, num_items, cmp);
217 return array.access(pos);
218 }
219
224 void reserve(size_t n)
225 {
226 ah_out_of_range_error_if(num_items > n) << "DynArrayHeap::reserve: n smaller than size";
227 array.reserve(n);
228 }
229
234 T &insert_direct(const T & key)
235 {
236 array(++num_items) = key; // place new element
237 const size_t pos = sift_up(array, 1, num_items, cmp);
238 return array.access(pos);
239 }
240
243 {
244 array(++num_items) = std::move(key); // place new element
245 const size_t pos = sift_up(array, 1, num_items, cmp);
246 return array.access(pos);
247 }
248
250 T &put(const T & key) { return insert(key); }
251
253 T &put(T && key) { return insert(std::move(key)); }
254
256 T &append(const T & key) { return insert(key); }
257
259 T &append(T && key) { return insert(std::move(key)); }
260
269 {
270 ah_underflow_error_if(num_items == 0) << "Heap is empty";
271
272 T & a1 = array(1);
273 T ret_val = std::move(a1);
274 if (num_items > 1)
275 {
276 a1 = std::move(array(num_items));
277 --num_items;
279 }
280 else
281 --num_items;
282
283 array.cut(num_items + 1);
284
285 return ret_val;
286 }
287
290 {
291 return getMin();
292 }
293
296 {
297 return getMin();
298 }
299
301 [[nodiscard]] constexpr size_t size() const noexcept { return num_items; }
302
304 [[nodiscard]] constexpr bool is_empty() const noexcept { return num_items == 0; }
305
306 struct Iterator : DynArray<T>::Iterator
307 {
308 using Base = typename DynArray<T>::Iterator;
309
311 {
312 if (h.num_items != 0)
313 this->next_ne();
314 }
315
316 Iterator() = default;
317
319 {
320 return this->curr_idx != 0 and this->curr_idx != this->array_ptr->size();
321 }
322
323 [[nodiscard]] long get_pos() const noexcept { return this->Base::get_pos() - 1; }
324 };
325
332 template <class Operation>
334 {
335 for (Iterator it(*this); it.has_curr(); it.next_ne())
336 if (not operation(it.get_curr()))
337 return false;
338 return true;
339 }
340
341 template <class Operation>
343 {
344 return const_cast<DynArrayHeap &>(*this).traverse<Operation>(operation);
345 }
346
347 template <class Operation>
349 {
351 }
352
353 template <class Operation>
355 {
357 }
358 };
359} // end namespace Aleph
360
361# endif // TPL_DYNARRAYHEAP_H
#define Args_Ctor(Name, Type)
Exception handling system with formatted messages for Aleph-w.
#define ah_out_of_range_error_if(C)
Throws std::out_of_range if condition holds.
Definition ah-errors.H:579
#define ah_underflow_error_if(C)
Throws std::underflow_error if condition holds.
Definition ah-errors.H:368
#define Special_Ctors(Set_Type, Type)
Generates special constructors for containers.
Definition ahDry.H:113
long double h
Definition btreepic.C:154
Dynamic heap (priority queue) backed by DynArray.
T & insert_direct(T &&key)
Move overload of insert_direct().
static size_t r_index(const size_t &i) noexcept
DynArrayHeap(Compare cmp_fct=Compare())
Default constructor.
T & put(T &&key)
Alias for insert() (move overload).
void reserve(size_t n)
Ensure the underlying array has capacity for at least n elements.
constexpr bool is_empty() const noexcept
Return true if the heap is empty.
T getMin()
Remove and return the top element.
bool traverse(Operation &operation)
Traverse all elements in the heap.
T & put(const T &key)
Alias for insert().
bool traverse(Operation &operation) const
T & append(const T &key)
Alias for insert().
bool traverse(Operation &&operation=Operation()) const
T & insert(const T &key)
Insert a copy of key into the heap.
bool traverse(Operation &&operation=Operation())
T & insert(T &&key)
Insert a key by moving it into the heap.
T & top()
Return the element with highest priority (the heap top).
T & insert_direct(const T &key)
Insert by directly indexing into the backing array.
const T & top() const
Const overload of top().
T & append(T &&key)
Alias for insert() (move overload).
constexpr size_t size() const noexcept
Return the number of elements.
Iterator on the items of array.
void next_ne() noexcept
Move the iterator one position forward guaranteeing no exception.
size_t size() const noexcept
Return the current dimension of array.
Equality test for containers.
Definition ah-dry.H:1534
Common methods to the Aleph-w ( ) containers.
Definition ah-dry.H:548
Aleph::DynList< __T > maps(Operation &op) const
Map the elements of the container.
Definition ah-dry.H:904
Common sequential searching methods on containers.
Definition ah-dry.H:164
Mixin that adds STL begin()/end() and cbegin()/cend() to Aleph containers.
int cmp(const __gmp_expr< T, U > &expr1, const __gmp_expr< V, W > &expr2)
Definition gmpfrxx.h:4118
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
size_t l_index(const size_t i)
Map a binary heap index to the index of its left child.
Definition ahUtils.H:213
void sift_down(T *ptr, const size_t l, const size_t r, Compare &cmp)
Restore the heap property by moving the element at position l downwards.
std::decay_t< typename HeadC::Item_Type > T
Definition ah-zip.H:107
size_t u_index(const size_t &i)
Map a binary heap index to the index of its parent.
Definition ahUtils.H:199
T & sift_up(T *ptr, const size_t l, const size_t r, Compare &cmp)
Restore the heap property by moving the element at position r upwards.
DynList< T > maps(const C &c, Op op)
Classic map operation.
typename DynArray< T >::Iterator Base
bool has_curr() const noexcept
Iterator(const DynArrayHeap &h) noexcept
long get_pos() const noexcept
Generic list of items stored in a container.
Definition ah-dry.H:1501
Lazy and scalable dynamic array implementation.
DynList< int > l