5#ifndef BOUNDED_PRIORITY_DEQUE_H
6#define BOUNDED_PRIORITY_DEQUE_H
35 template <typename U, typename = decltype(std::declval<U>()(std::declval<const T&>(), std::declval<const T&>()))>
36 static std::true_type check(U*);
38 static std::false_type check(...);
41 static constexpr bool value =
decltype(check(std::declval<T*>()))::value;
55template<
typename K,
typename V,
typename Enable =
void>
62 return this->key < other.
key;
75template<
typename K,
typename V>
76class BoundingPair<K, V, std::enable_if_t<has_comparison_operator_v<K>>> :
public std::pair<K, V> {
80 return comparator(this->
key, other.
key);
94template<
typename K,
typename V>
97 std::vector<BoundingPair<K, V>> _buffer;
98 size_t _k, _size = 0, _head = 0, _tail = 0;
115 [[nodiscard]]
size_t nextIndex(
size_t current)
const {
return (current + 1) % _k; }
123 [[nodiscard]]
size_t prevIndex(
size_t current)
const {
return (current + _k - 1) % _k; }
137 while (start != end) {
138 size_t mid = start + (end - start) / 2;
139 if (
compare(_buffer[(_head + mid) % _k].key, target.
key)) start = mid + 1;
142 return (_head + start) % _k;
158 _buffer[0] = element;
171 else if (_head <= _tail && _head > 0) {
172 std::move(_buffer.begin() + _head, _buffer.begin() + index + 1, _buffer.begin() + _head - 1);
175 std::move_backward(_buffer.begin() + index, _buffer.begin() + _tail + 1, _buffer.begin() + _tail + 2);
179 _buffer[index] = element;
188 if (--_size == 0)
clear();
196 if (--_size == 0)
clear();
214 if (
empty())
throw std::runtime_error(
"Attempted to access top element of empty BoundedPriorityDeque");
216 return _buffer[_head];
228 if (
empty())
throw std::runtime_error(
"Attempted to access bottom element of empty BoundedPriorityDeque");
230 return _buffer[_tail];
243 if (
empty())
throw std::runtime_error(
"Attempted to access bottom element of empty BoundedPriorityDeque");
245 return _buffer[_head].key;
257 if (
empty())
throw std::runtime_error(
"Attempted to access bottom element of empty BoundedPriorityDeque");
259 return _buffer[_tail].key;
304 return _buffer[_head <= _tail ? _head + offsetTop : (_head + offsetTop) % _k];
314 if (
empty())
throw std::runtime_error(
"Attempted to pop from empty BoundedPriorityDeque");
318 return _buffer[index];
328 if (
empty())
throw std::runtime_error(
"Attempted to pop from empty BoundedPriorityDeque");
332 return _buffer[index];
345 for (
size_t i = 0; i < rhs.
size(); ++i) {
369 [[nodiscard]]
size_t size()
const {
return _size; }
375 [[nodiscard]]
size_t capacity()
const {
return _k; }
381 [[nodiscard]]
bool empty()
const {
return _size == 0; }
387 [[nodiscard]]
bool full()
const {
return _size == _k; }
401 std::vector<BoundingPair<K, V>> newBuffer(k);
403 if (_head <= _tail) {
404 size_t elementsToCopy = std::min(_size, k);
405 std::move(_buffer.begin() + _head, _buffer.begin() + _head + elementsToCopy, newBuffer.begin());
406 _size = elementsToCopy;
408 size_t topSize = _k - _head;
409 size_t bottomSize = _tail + 1;
410 size_t elementsToCopyTop = std::min(topSize, k);
411 size_t elementsToCopyBottom = std::min(bottomSize, k - elementsToCopyTop);
413 std::move(_buffer.begin() + _head, _buffer.begin() + _head + elementsToCopyTop, newBuffer.begin());
414 std::move(_buffer.begin(), _buffer.begin() + elementsToCopyBottom, newBuffer.begin() + elementsToCopyTop);
416 _size = elementsToCopyTop + elementsToCopyBottom;
419 _buffer.swap(newBuffer);
435template<
typename K,
typename V>
438 [[nodiscard]]
bool compare(K a, K b)
const override {
return a < b; }
453template<
typename K,
typename V>
456 [[nodiscard]]
bool compare(K a, K b)
const override {
return a > b; }
474template<
typename K,
typename V,
typename Comparator = std::less<K>>
477 Comparator comparator;
479 [[nodiscard]]
bool compare(K a, K b)
const override {
return comparator(a, b); }
502template<typename V, typename Comparator, typename K = decltype(std::declval<Comparator>().comparisonValue(std::declval<V>()))>
505 Comparator comparator;
507 [[nodiscard]]
bool compare(K a, K b)
const override {
508 return comparator(a, b);
511 K extractKey(
const V& value)
const {
512 return comparator.comparisonValue(value);
519 void emplace(
const V& value) {
520 K key = extractKey(value);
524 void push(
const V& value) { emplace(value); }
Lightweight maximum priority dequeue.
Definition BoundedPriorityDeque.hpp:454
bool compare(K a, K b) const override
Definition BoundedPriorityDeque.hpp:456
Lightweight minimum priority dequeue.
Definition BoundedPriorityDeque.hpp:436
bool compare(K a, K b) const override
Definition BoundedPriorityDeque.hpp:438
Base class for implementing a bounded priority deque.
Definition BoundedPriorityDeque.hpp:95
void insert(const BoundingPair< K, V > &element)
Inserts an element into the _buffer.
Definition BoundedPriorityDeque.hpp:156
size_t prevIndex(size_t current) const
Provides fast access to the previous index of a given insertion position.
Definition BoundedPriorityDeque.hpp:123
BoundingPair< K, V > popBottom()
remove the lowest-priority element.
Definition BoundedPriorityDeque.hpp:326
BoundingPair< K, V > pop()
remove the highest-priority element.
Definition BoundedPriorityDeque.hpp:312
size_t size() const
Definition BoundedPriorityDeque.hpp:369
BoundingPair< K, V > top() const
Get the highest-priority element.
Definition BoundedPriorityDeque.hpp:212
void resize(size_t k)
Sets the capacity and restores clean state.
Definition BoundedPriorityDeque.hpp:398
K topK() const
Get the key from the highest-priority element.
Definition BoundedPriorityDeque.hpp:241
size_t capacity() const
Definition BoundedPriorityDeque.hpp:375
virtual bool compare(K a, K b) const =0
BoundedPriorityDequeBase(size_t capacity=0)
Primary constructor with default bounding capacity of zero.
Definition BoundedPriorityDeque.hpp:205
void push(const BoundingPair< K, V > &element)
Inserts an element into the vector.
Definition BoundedPriorityDeque.hpp:285
bool empty() const
Definition BoundedPriorityDeque.hpp:381
void clear()
clears and resets the data structure.
Definition BoundedPriorityDeque.hpp:359
void operator+=(const BoundedPriorityDequeBase< K, V > &rhs)
Merges another BoundedPriorityDeque instance into the calling instance.
Definition BoundedPriorityDeque.hpp:344
BoundingPair< K, V > bottom() const
Get the lowest-priority element.
Definition BoundedPriorityDeque.hpp:226
size_t binarySearch(const BoundingPair< K, V > &target) const
Efficiently locates the optimal insertion index.
Definition BoundedPriorityDeque.hpp:134
K bottomK() const
Get the key from the lowest-priority element.
Definition BoundedPriorityDeque.hpp:255
bool full() const
Definition BoundedPriorityDeque.hpp:387
void _popBottom()
Internal method with no return val.
Definition BoundedPriorityDeque.hpp:194
BoundingPair< K, V > operator[](size_t offsetTop) const
random accessor relative to the top of the deque.
Definition BoundedPriorityDeque.hpp:303
size_t nextIndex(size_t current) const
Provides fast access to the next index of a given insertion position.
Definition BoundedPriorityDeque.hpp:115
void emplace(K key, const V &value)
constructs a BoundingPair<K, V> element and inserts it.
Definition BoundedPriorityDeque.hpp:268
void _popTop()
Internal method with no return val.
Definition BoundedPriorityDeque.hpp:186
Lightweight custom key comparator priority dequeue.
Definition BoundedPriorityDeque.hpp:475
bool compare(K a, K b) const override
Definition BoundedPriorityDeque.hpp:479
Lightweight custom value-based comparator priority dequeue.
Definition BoundedPriorityDeque.hpp:503
bool compare(K a, K b) const override
Definition BoundedPriorityDeque.hpp:507
A template class to store key-value pairs with comparison operations.
Definition BoundedPriorityDeque.hpp:56
K key
The key of the pair.
Definition BoundedPriorityDeque.hpp:58
V value
The value of the pair.
Definition BoundedPriorityDeque.hpp:59
Type trait to detect the presence of a comparison operator in types.
Definition BoundedPriorityDeque.hpp:34