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/>.
8 /** @file binaryheap.hpp Binary heap implementation. */
10 #ifndef BINARYHEAP_HPP
11 #define BINARYHEAP_HPP
13 #include "../core/alloc_func.hpp"
15 /** Enable it if you suspect binary heap doesn't work well */
16 #define BINARYHEAP_CHECK 0
19 /** Check for consistency. */
20 #define CHECK_CONSISTY() this->CheckConsistency()
22 /** Don't check for consistency. */
23 #define CHECK_CONSISTY() ;
27 * Binary Heap as C++ template.
28 * A carrier which keeps its items automatically holds the smallest item at
29 * the first position. The order of items is maintained by using a binary tree.
30 * The implementation is used for priority queue's.
32 * @par Usage information:
33 * Item of the binary heap should support the 'lower-than' operator '<'.
34 * It is used for comparing items before moving them to their position.
37 * This binary heap allocates just the space for item pointers. The items
38 * are allocated elsewhere.
40 * @par Implementation notes:
41 * Internally the first item is never used, because that simplifies the
45 * For further information about the Binary Heap algorithm, see
46 * http://www.policyalmanac.org/games/binaryHeaps.htm
48 * @tparam T Type of the items stored in the binary heap
53 uint items
; ///< Number of items in the heap
54 uint capacity
; ///< Maximum number of items the heap can hold
55 T
**data
; ///< The pointer to the heap item pointers
59 * Create a binary heap.
60 * @param max_items The limit of the heap
62 explicit CBinaryHeapT(uint max_items
)
66 this->data
= MallocT
<T
*>(max_items
+ 1);
78 * Get position for fixing a gap (downwards).
79 * The gap is moved downwards in the binary tree until it
82 * @param gap The position of the gap
83 * @param item The proposed item for filling the gap
84 * @return The (gap)position where the item fits
86 inline uint
HeapifyDown(uint gap
, T
*item
)
90 /* The first child of the gap is at [parent * 2] */
93 /* while children are valid */
94 while (child
<= this->items
) {
95 /* choose the smaller child */
96 if (child
< this->items
&& *this->data
[child
+ 1] < *this->data
[child
]) {
99 /* is it smaller than our parent? */
100 if (!(*this->data
[child
] < *item
)) {
101 /* the smaller child is still bigger or same as parent => we are done */
104 /* if smaller child is smaller than parent, it will become new parent */
105 this->data
[gap
] = this->data
[child
];
107 /* where do we have our new children? */
114 * Get position for fixing a gap (upwards).
115 * The gap is moved upwards in the binary tree until the
118 * @param gap The position of the gap
119 * @param item The proposed item for filling the gap
120 * @return The (gap)position where the item fits
122 inline uint
HeapifyUp(uint gap
, T
*item
)
129 /* compare [gap] with its parent */
131 if (!(*item
< *this->data
[parent
])) {
132 /* we don't need to continue upstairs */
135 this->data
[gap
] = this->data
[parent
];
142 /** Verify the heap consistency */
143 inline void CheckConsistency()
145 for (uint child
= 2; child
<= this->items
; child
++) {
146 uint parent
= child
/ 2;
147 assert(!(*this->data
[child
] < *this->data
[parent
]));
154 * Get the number of items stored in the priority queue.
156 * @return The number of items in the queue
158 inline uint
Length() const
164 * Test if the priority queue is empty.
166 * @return True if empty
168 inline bool IsEmpty() const
170 return this->items
== 0;
174 * Test if the priority queue is full.
176 * @return True if full.
178 inline bool IsFull() const
180 return this->items
>= this->capacity
;
184 * Get the smallest item in the binary tree.
186 * @return The smallest item, or throw assert if empty.
190 assert(!this->IsEmpty());
191 return this->data
[1];
195 * Get the LAST item in the binary tree.
197 * @note The last item is not necessary the biggest!
199 * @return The last item
203 return this->data
[1 + this->items
];
207 * Insert new item into the priority queue, maintaining heap order.
209 * @param new_item The pointer to the new item
211 inline void Include(T
*new_item
)
213 if (this->IsFull()) {
214 assert(this->capacity
< UINT_MAX
/ 2);
217 this->data
= ReallocT
<T
*>(this->data
, this->capacity
+ 1);
220 /* Make place for new item. A gap is now at the end of the tree. */
221 uint gap
= this->HeapifyUp(++items
, new_item
);
222 this->data
[gap
] = new_item
;
227 * Remove and return the smallest (and also first) item
228 * from the priority queue.
230 * @return The pointer to the removed item
234 assert(!this->IsEmpty());
236 T
*first
= this->Begin();
239 /* at index 1 we have a gap now */
240 T
*last
= this->End();
241 uint gap
= this->HeapifyDown(1, last
);
242 /* move last item to the proper place */
243 if (!this->IsEmpty()) this->data
[gap
] = last
;
250 * Remove item at given index from the priority queue.
252 * @param index The position of the item in the heap
254 inline void Remove(uint index
)
256 if (index
< this->items
) {
259 /* at position index we have a gap now */
261 T
*last
= this->End();
262 /* Fix binary tree up and downwards */
263 uint gap
= this->HeapifyUp(index
, last
);
264 gap
= this->HeapifyDown(gap
, last
);
265 /* move last item to the proper place */
266 if (!this->IsEmpty()) this->data
[gap
] = last
;
268 assert(index
== this->items
);
275 * Search for an item in the priority queue.
276 * Matching is done by comparing address of the
279 * @param item The reference to the item
280 * @return The index of the item or zero if not found
282 inline uint
FindIndex(const T
&item
) const
284 if (this->IsEmpty()) return 0;
285 for (T
**ppI
= this->data
+ 1, **ppLast
= ppI
+ this->items
; ppI
<= ppLast
; ppI
++) {
287 return ppI
- this->data
;
294 * Make the priority queue empty.
295 * All remaining items will remain untouched.
303 #endif /* BINARYHEAP_HPP */