3 #include "../utility/assert.h"
4 #include "../utility/empty_base.h"
20 template<
typename T,
typename Comp,
typename Alloc>
24 static_assert(std::is_move_constructible_v<T>,
"T must be move constructible");
25 static_assert(std::is_move_assignable_v<T>,
"T must be move assignable");
27 static_assert(std::is_default_constructible_v<Alloc> || std::is_copy_constructible_v<Alloc>,
"The allocator must be default or copy constructible");
29 typedef std::allocator_traits<Alloc> Traits;
55 binary_heap(
const Alloc& allocator,
const Comp& comp = Comp()) noexcept :
72 m_Begin(Traits::allocate(m_Alloc,
capacity)) {}
85 m_Begin(Traits::allocate(m_Alloc,
capacity)) {}
92 binary_heap(std::initializer_list<T> initializer,
const Comp& comp = Comp()) :
96 m_Capacity(initializer.
size()),
97 m_Begin(Traits::allocate(m_Alloc, initializer.
size()))
99 for (
auto value : initializer)
109 binary_heap(std::initializer_list<T> initializer,
const Alloc& allocator,
const Comp& comp = Comp()) :
113 m_Capacity(initializer.
size()),
114 m_Begin(Traits::allocate(m_Alloc, initializer.
size()))
116 for (
auto value : initializer)
121 m_Alloc(Traits::select_on_container_copy_construction(other.m_Alloc)),
122 m_Comp(other.m_Comp),
123 m_Size(other.m_Size),
124 m_Capacity(other.m_Size),
125 m_Begin(Traits::allocate(m_Alloc, other.m_Size))
127 for (
size_t i = 0; i < m_Size; i++)
128 Traits::construct(m_Alloc, m_Begin + i, other.m_Begin[i]);
132 m_Alloc(std::move(other.m_Alloc)),
133 m_Comp(other.m_Comp),
134 m_Size(other.m_Size),
135 m_Capacity(other.m_Capacity),
136 m_Begin(std::move(other.m_Begin))
138 other.m_Capacity = 0;
140 other.m_Begin =
nullptr;
145 m_Comp(other.m_Comp),
146 m_Size(other.m_Size),
147 m_Capacity(other.m_Size),
148 m_Begin(Traits::allocate(m_Alloc, other.m_Size))
150 for (
size_t i = 0; i < m_Size; i++)
151 Traits::construct(m_Alloc, m_Begin + i, other.m_Begin[i]);
156 m_Comp(std::move(other.m_Comp)),
157 m_Size(other.m_Size),
158 m_Capacity(other.m_Size),
159 m_Begin(Traits::allocate(m_Alloc, other.m_Size))
162 for (
size_t i = 0; i < m_Size; i++)
163 Traits::construct(m_Alloc, m_Begin + i, other.m_Begin[i]);
165 if (other.m_Begin !=
nullptr)
166 Traits::deallocate(other.m_Alloc, other.m_Begin, other.m_Capacity *
sizeof(T));
168 other.m_Capacity = 0;
170 other.m_Begin =
nullptr;
178 for (
size_t i = 0; i < m_Size; i++)
179 Traits::destroy(m_Alloc, m_Begin + i);
181 Traits::deallocate(m_Alloc, m_Begin, m_Capacity);
189 for (
size_t i = 0; i < m_Size; i++)
190 Traits::destroy(m_Alloc, m_Begin + i);
192 Traits::deallocate(m_Alloc, m_Begin, m_Capacity);
195 m_Alloc = other.m_Alloc;
196 m_Comp = other.m_Comp;
197 m_Size = other.m_Size;
198 m_Capacity = other.m_Size;
199 m_Begin = Traits::allocate(m_Alloc, m_Capacity);
202 for (
size_t i = 0; i < m_Size; i++)
203 Traits::construct(m_Alloc, m_Begin + i, other.m_Begin[i]);
213 for (
size_t i = 0; i < m_Size; i++)
214 Traits::destroy(m_Alloc, m_Begin + i);
216 Traits::deallocate(m_Alloc, m_Begin, m_Capacity);
219 m_Alloc = std::move(other.m_Alloc);
220 m_Comp = std::move(other.m_Comp);
221 m_Size = other.m_Size;
222 m_Capacity = other.m_Capacity;
223 m_Begin = other.m_Begin;
225 other.m_Capacity = 0;
227 other.m_Begin =
nullptr;
266 size_t size() const noexcept {
return m_Size; }
272 size_t capacity() const noexcept {
return m_Capacity; }
278 bool empty() const noexcept {
return m_Size == 0; }
300 if (m_Size == m_Capacity)
303 Traits::construct(m_Alloc, m_Begin + m_Size, std::forward<V>(value));
305 size_t index = percolateUp(m_Size++);
307 return m_Begin + index;
331 m_Begin[0] = std::move(m_Begin[--m_Size]);
332 Traits::destroy(m_Alloc, m_Begin + m_Size);
345 for (
size_t i = 0; i < m_Size; i++)
347 if (m_Begin[i] == value)
351 return m_Begin + m_Size;
359 for (
size_t i = 0; i < m_Size; i++)
360 Traits::destroy(m_Alloc, m_Begin + i);
366 void expand(
size_t n) noexcept
369 size_t alSize = curCap + (std::max)(curCap, n);
374 void set_size(
size_t n) noexcept
376 size_t curSize = (std::min)(
size(), n);
378 T* newData = Traits::allocate(m_Alloc, n);
383 for (
size_t i = 0; i < curSize; i++)
384 Traits::construct(m_Alloc, newData + i, std::move(m_Begin[i]));
387 for (
size_t i = 0; i < m_Size; i++)
388 Traits::destroy(m_Alloc, m_Begin + i);
391 Traits::deallocate(m_Alloc, m_Begin, m_Capacity);
399 constexpr
size_t parent(
size_t index)
const noexcept
401 return (index - 1) / 2;
404 constexpr
size_t left(
size_t index)
const noexcept
406 return index * 2 + 1;
409 constexpr
size_t right(
size_t index)
const noexcept
411 return index * 2 + 2;
414 size_t percolateUp(
size_t index)
416 const T value = m_Begin[index];
418 while (index != 0 && m_Comp(value, m_Begin[parent(index)]))
420 m_Begin[index] = std::move(m_Begin[parent(index)]);
421 index = parent(index);
424 m_Begin[index] = std::move(value);
429 void percolateDown(
size_t index) noexcept
431 size_t parent = index;
433 const T value = m_Begin[index];
435 while (parent < m_Size)
437 size_t l = left(parent);
438 size_t r = right(parent);
440 size_t child = parent;
442 if (l < m_Size && m_Comp(m_Begin[l], m_Begin[child]))
445 if (r < m_Size && m_Comp(m_Begin[r], m_Begin[child]))
451 const T temp(std::move(m_Begin[child]));
452 m_Begin[child] = std::move(m_Begin[parent]);
453 m_Begin[parent] = std::move(temp);
458 m_Begin[parent] = std::move(value);
#define KTL_ASSERT(x)
Definition: assert.h:17
A priority queue implemented as a binary heap.
Definition: binary_heap.h:22
size_t capacity() const noexcept
Returns the current capacity of the heap.
Definition: binary_heap.h:272
binary_heap(const Alloc &allocator, const Comp &comp=Comp()) noexcept
Construct the binary heap with the given allocator and comparator.
Definition: binary_heap.h:55
std::reverse_iterator< const T * > const_reverse_iterator
Definition: binary_heap.h:36
iterator data() noexcept
Returns an iterator to the start of the heap.
Definition: binary_heap.h:254
binary_heap(binary_heap &&other) noexcept(std::is_nothrow_move_constructible_v< T >)
Definition: binary_heap.h:131
binary_heap(size_t capacity, const Alloc &allocator, const Comp &comp=Comp()) noexcept
Construct the binary heap with the given allocator, comparator and an initial capacity.
Definition: binary_heap.h:80
const_reverse_iterator rbegin() const noexcept
Definition: binary_heap.h:243
iterator find(const T &value) const noexcept
Returns an iterator to the element index. Takes O(n) time.
Definition: binary_heap.h:343
size_t size() const noexcept
Returns the current size of the heap.
Definition: binary_heap.h:266
~binary_heap()
Definition: binary_heap.h:173
iterator insert(V &&value) noexcept
Inserts a new element into the heap via perfect forwarding.
Definition: binary_heap.h:298
reverse_iterator rbegin() noexcept
Definition: binary_heap.h:241
binary_heap & operator=(binary_heap &&other) noexcept(std::is_nothrow_move_assignable_v< T >)
Definition: binary_heap.h:208
void reserve(size_t n) noexcept
Reserves the capacity of the heap to n, without initializing any elements.
Definition: binary_heap.h:285
binary_heap(const binary_heap &other) noexcept(std::is_nothrow_copy_constructible_v< T >)
Definition: binary_heap.h:120
const_iterator begin() const noexcept
Definition: binary_heap.h:235
iterator begin() noexcept
Definition: binary_heap.h:233
binary_heap(const binary_heap &other, const Alloc &allocator) noexcept(std::is_nothrow_copy_constructible_v< T >)
Definition: binary_heap.h:143
binary_heap & operator=(const binary_heap &other) noexcept(std::is_nothrow_copy_assignable_v< T >)
Definition: binary_heap.h:185
binary_heap(size_t capacity, const Comp &comp=Comp()) noexcept
Construct the binary heap with the given comparator and an initial capacity.
Definition: binary_heap.h:67
const_iterator data() const noexcept
Returns a const iterator to the start of the heap.
Definition: binary_heap.h:260
const_reverse_iterator rend() const noexcept
Definition: binary_heap.h:247
const_iterator end() const noexcept
Definition: binary_heap.h:239
void clear() noexcept
Clear all elements in the heap, destroying each element.
Definition: binary_heap.h:357
binary_heap(const Comp &comp=Comp()) noexcept
Construct the binary heap with the given comparator.
Definition: binary_heap.h:43
iterator end() noexcept
Definition: binary_heap.h:237
const T * const_iterator
Definition: binary_heap.h:33
binary_heap(std::initializer_list< T > initializer, const Alloc &allocator, const Comp &comp=Comp())
Construct the binary heap with the given allocator, comparator and an initial set of values.
Definition: binary_heap.h:109
std::reverse_iterator< T * > reverse_iterator
Definition: binary_heap.h:35
bool empty() const noexcept
Returns true if the heap has no elements.
Definition: binary_heap.h:278
T * iterator
Definition: binary_heap.h:32
reverse_iterator rend() noexcept
Definition: binary_heap.h:245
binary_heap(binary_heap &&other, const Alloc &allocator) noexcept(std::is_nothrow_move_constructible_v< T >)
Definition: binary_heap.h:154
T & peek() noexcept
Peeks at the root element (lowest or highest, depending on min or max heap) and returns a reference t...
Definition: binary_heap.h:314
binary_heap(std::initializer_list< T > initializer, const Comp &comp=Comp())
Construct the binary heap with the given comparator and an initial set of values.
Definition: binary_heap.h:92
T pop() noexcept
Removes the root element (lowest or highest, depending on min or max heap) and returns it.
Definition: binary_heap.h:325
#define KTL_EMPTY_BASE
Definition: empty_base.h:6
Definition: cascading.h:15