fennec
Loading...
Searching...
No Matches
priority_queue.h
Go to the documentation of this file.
1// =====================================================================================================================
2// fennec, a free and open source game engine
3// Copyright © 2025 Medusa Slockbower
4//
5// This program is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with this program. If not, see <https://www.gnu.org/licenses/>.
17// =====================================================================================================================
18
30
31#ifndef FENNEC_CONTAINERS_PRIORITY_QUEUE_H
32#define FENNEC_CONTAINERS_PRIORITY_QUEUE_H
33
35#include <fennec/lang/compare.h>
36#include <fennec/lang/types.h>
38
39// Binary heaps are just kinda busted.
40// In-array binary heaps are one of the most efficient data structures for computers
41// -> Cache Locality
42// -> log(n) runtime
43// -> No auxiliary structures or constant runtimes
44//
45// I tried just about every heap under the sun
46// -> strict fibonacci heap, got blown out of the water by std::priority_queue
47// -> fibonacci heap, got blown out of the water by std::priority_queue
48// -> binomial heap, on-par with std::set, blown out of the water by std::priority_queue
49//
50// Then I relented and fell back to ye old binary heap
51// This implementation roughly matches gcc's std::priority_queue
52
53namespace fennec
54{
55
56template<typename ValueT, class CompareT = less<ValueT>, class AllocT = allocator<ValueT>>
57struct priority_queue {
58
59// Definitions & Constants =============================================================================================
60public:
61 using value_t = ValueT;
62 using compare_t = CompareT;
63 using alloc_t = allocation<value_t, AllocT>;
64
65 static constexpr size_t npos = -1;
66
67private:
68 constexpr size_t left(size_t n) const {
69 n = n * 2 + 1;
70 return n >= _size ? npos : n;
71 }
72
73 constexpr size_t right(size_t n) const {
74 n = n * 2 + 2;
75 return n >= _size ? npos : n;
76 }
77
78 constexpr size_t parent(size_t n) const {
79 return n == 0 ? npos : (n - 1) / 2;
80 }
81
82
83// Constructors & Destructor ===========================================================================================
84public:
85 constexpr priority_queue()
86 : _size(0) {
87 }
88
89 constexpr ~priority_queue() {
90 while (_size > 0) {
91 --_size;
92 fennec::destruct(&_table[_size]);
93 }
94 }
95
96
97// Properties ==========================================================================================================
98
99 constexpr size_t size() const {
100 return _size;
101 }
102
103 constexpr size_t capacity() const {
104 return _table.capacity();
105 }
106
107 constexpr bool empty() const {
108 return size() == 0;
109 }
110
111
112// Access ==============================================================================================================
113
114 constexpr const value_t& front() const {
115 return _table[0];
116 }
117
118
119// Modifiers ===========================================================================================================
120
121 constexpr void push(const value_t& key) {
122 this->_insert(key);
123 }
124
125 constexpr void push(value_t&& key) {
126 this->_insert(fennec::forward<value_t>(key));
127 }
128
129 template<typename...ArgsT>
130 constexpr void emplace(ArgsT&&...args) {
131 this->_insert(fennec::forward<ArgsT>(args)...);
132 }
133
134 constexpr void pop() {
135 fennec::swap(_table[0], _table[--_size]);
136 fennec::destruct(&_table[_size]);
137 _fix_erase(0);
138 }
139
140
141// Members =============================================================================================================
142private:
143 compare_t _compare;
144 alloc_t _table;
145 size_t _size;
146
147// Helpers =============================================================================================================
148
149 template<typename...ArgsT>
150 constexpr void _insert(ArgsT&&...args) {
151 if (_size == _table.capacity()) {
152 _expand();
153 }
154 fennec::construct(&_table[_size], fennec::forward<ArgsT>(args)...);
155 _fix_insert(_size++);
156 }
157
158 constexpr void _expand() {
159 _table.reallocate((_table.capacity() + 1) * 2 - 1);
160 }
161
162 constexpr size_t _min(size_t a, size_t b) {
163 if (a == npos) { return b; }
164 if (b == npos) { return a; }
165 return _compare(_table[a], _table[b]) ? a : b;
166 }
167
168 void _fix_insert(size_t n) {
169 size_t p = parent(n);
170 while (p != npos && _compare(_table[n], _table[p])) {
171 fennec::swap(_table[n], _table[p]);
172 n = p;
173 p = parent(n);
174 }
175 }
176
177 void _fix_erase(size_t n) {
178 size_t c = _min(left(n), right(n));
179 while (n != npos && c != npos && _compare(_table[c], _table[n])) {
180 fennec::swap(_table[c], _table[n]);
181 n = c;
182 c = _min(left(n), right(n));
183 }
184 }
185
186
187};
188
189}
190
191
192#endif // FENNEC_CONTAINERS_PRIORITY_QUEUE_H
This header contains structures and classes related to allocating blocks of memory.
A header containing the definition for a pool of objects associated by ids.
Types
constexpr void swap(T &x, T &y) noexcept
Swaps x and y.
Definition utility.h:114