OpenTTD Source 20241224-master-gf74b0cf984
binaryheap.hpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6 */
7
10#ifndef BINARYHEAP_HPP
11#define BINARYHEAP_HPP
12
14#define BINARYHEAP_CHECK 0
15
16#if BINARYHEAP_CHECK
18# define CHECK_CONSISTY() this->CheckConsistency()
19#else
21# define CHECK_CONSISTY() ;
22#endif
23
52template <class T>
54private:
55 size_t items = 0;
56 std::vector<T *> data;
57
58public:
63 explicit CBinaryHeapT(size_t initial_capacity)
64 {
65 this->data.reserve(initial_capacity);
66 this->Clear();
67 }
68
69protected:
79 inline size_t HeapifyDown(size_t gap, T *item)
80 {
81 assert(gap != 0);
82
83 /* The first child of the gap is at [parent * 2] */
84 size_t child = gap * 2;
85
86 /* while children are valid */
87 while (child <= this->items) {
88 /* choose the smaller child */
89 if (child < this->items && *this->data[child + 1] < *this->data[child]) {
90 child++;
91 }
92 /* is it smaller than our parent? */
93 if (!(*this->data[child] < *item)) {
94 /* the smaller child is still bigger or same as parent => we are done */
95 break;
96 }
97 /* if smaller child is smaller than parent, it will become new parent */
98 this->data[gap] = this->data[child];
99 gap = child;
100 /* where do we have our new children? */
101 child = gap * 2;
102 }
103 return gap;
104 }
105
115 inline size_t HeapifyUp(size_t gap, T *item)
116 {
117 assert(gap != 0);
118
119 size_t parent;
120
121 while (gap > 1) {
122 /* compare [gap] with its parent */
123 parent = gap / 2;
124 if (!(*item < *this->data[parent])) {
125 /* we don't need to continue upstairs */
126 break;
127 }
128 this->data[gap] = this->data[parent];
129 gap = parent;
130 }
131 return gap;
132 }
133
134#if BINARYHEAP_CHECK
136 inline void CheckConsistency()
137 {
138 assert(this->items == this->data.size() - 1);
139 for (size_t child = 2; child <= this->items; child++) {
140 size_t parent = child / 2;
141 assert(!(*this->data[child] < *this->data[parent]));
142 }
143 }
144#endif
145
146public:
152 inline size_t Length() const
153 {
154 return this->items;
155 }
156
162 inline bool IsEmpty() const
163 {
164 return this->items == 0;
165 }
166
172 inline T *Begin()
173 {
174 assert(!this->IsEmpty());
175 return this->data[1];
176 }
177
185 inline T *End()
186 {
187 return this->data[1 + this->items];
188 }
189
195 inline void Include(T *new_item)
196 {
197 /* Make place for new item. A gap is now at the end of the tree. */
198 this->data.emplace_back();
199 size_t gap = this->HeapifyUp(++items, new_item);
200 this->data[gap] = new_item;
202 }
203
210 inline T *Shift()
211 {
212 assert(!this->IsEmpty());
213
214 T *first = this->Begin();
215
216 this->items--;
217 /* at index 1 we have a gap now */
218 T *last = this->End();
219 size_t gap = this->HeapifyDown(1, last);
220 /* move last item to the proper place */
221 if (!this->IsEmpty()) this->data[gap] = last;
222 this->data.pop_back();
223
225 return first;
226 }
227
233 inline void Remove(size_t index)
234 {
235 if (index < this->items) {
236 assert(index != 0);
237 this->items--;
238 /* at position index we have a gap now */
239
240 T *last = this->End();
241 /* Fix binary tree up and downwards */
242 size_t gap = this->HeapifyUp(index, last);
243 gap = this->HeapifyDown(gap, last);
244 /* move last item to the proper place */
245 if (!this->IsEmpty()) this->data[gap] = last;
246 } else {
247 assert(index == this->items);
248 this->items--;
249 }
250 this->data.pop_back();
251
253 }
254
263 inline size_t FindIndex(const T &item) const
264 {
265 auto it = std::ranges::find(this->data, &item);
266 return it == this->data.end() ? 0 : std::distance(this->data.begin(), it);
267 }
268
273 inline void Clear()
274 {
275 this->items = 0;
276 this->data.resize(1);
277
279 }
280};
281
282#endif /* BINARYHEAP_HPP */
#define CHECK_CONSISTY()
Don't check for consistency.
Binary Heap as C++ template.
void Remove(size_t index)
Remove item at given index from the priority queue.
CBinaryHeapT(size_t initial_capacity)
Create a binary heap.
void Include(T *new_item)
Insert new item into the priority queue, maintaining heap order.
size_t items
Number of valid items in the heap.
size_t FindIndex(const T &item) const
Search for an item in the priority queue.
std::vector< T * > data
The pointer to the heap item pointers.
T * Shift()
Remove and return the smallest (and also first) item from the priority queue.
size_t Length() const
Get the number of items stored in the priority queue.
bool IsEmpty() const
Test if the priority queue is empty.
T * End()
Get the LAST item in the binary tree.
void Clear()
Make the priority queue empty.
size_t HeapifyDown(size_t gap, T *item)
Get position for fixing a gap (downwards).
size_t HeapifyUp(size_t gap, T *item)
Get position for fixing a gap (upwards).
T * Begin()
Get the smallest item in the binary tree.