diff --git a/src/misc/binaryheap.hpp b/src/misc/binaryheap.hpp index d3dfdfdefa..377d4d9548 100644 --- a/src/misc/binaryheap.hpp +++ b/src/misc/binaryheap.hpp @@ -10,8 +10,6 @@ #ifndef BINARYHEAP_HPP #define BINARYHEAP_HPP -#include "../core/alloc_func.hpp" - /** Enable it if you suspect binary heap doesn't work well */ #define BINARYHEAP_CHECK 0 @@ -27,7 +25,11 @@ * Binary Heap as C++ template. * A carrier which keeps its items automatically holds the smallest item at * the first position. The order of items is maintained by using a binary tree. - * The implementation is used for priority queue's. + * The implementation is used for priority queues. + * + * There are two major differences compared to std::priority_queue. First the + * std::priority_queue does not support indexing/removing elements in the + * middle of the heap/queue and second it has the biggest item first. * * @par Usage information: * Item of the binary heap should support the 'lower-than' operator '<'. @@ -50,27 +52,18 @@ template class CBinaryHeapT { private: - size_t items; ///< Number of items in the heap - size_t capacity; ///< Maximum number of items the heap can hold - T **data; ///< The pointer to the heap item pointers + size_t items = 0; ///< Number of valid items in the heap + std::vector data; ///< The pointer to the heap item pointers public: /** * Create a binary heap. - * @param max_items The limit of the heap + * @param initial_capacity The initial reserved capacity for the heap. */ - explicit CBinaryHeapT(size_t max_items) - : items(0) - , capacity(max_items) - { - this->data = MallocT(max_items + 1); - } - - ~CBinaryHeapT() + explicit CBinaryHeapT(size_t initial_capacity) { + this->data.reserve(initial_capacity); this->Clear(); - free(this->data); - this->data = nullptr; } protected: @@ -142,6 +135,7 @@ protected: /** Verify the heap consistency */ inline void CheckConsistency() { + assert(this->items == this->data.size() - 1); for (size_t child = 2; child <= this->items; child++) { size_t parent = child / 2; assert(!(*this->data[child] < *this->data[parent])); @@ -170,16 +164,6 @@ public: return this->items == 0; } - /** - * Test if the priority queue is full. - * - * @return True if full. - */ - inline bool IsFull() const - { - return this->items >= this->capacity; - } - /** * Get the smallest item in the binary tree. * @@ -210,14 +194,8 @@ public: */ inline void Include(T *new_item) { - if (this->IsFull()) { - assert(this->capacity < UINT_MAX / 2); - - this->capacity *= 2; - this->data = ReallocT(this->data, this->capacity + 1); - } - /* Make place for new item. A gap is now at the end of the tree. */ + this->data.emplace_back(); size_t gap = this->HeapifyUp(++items, new_item); this->data[gap] = new_item; CHECK_CONSISTY(); @@ -241,6 +219,7 @@ public: size_t gap = this->HeapifyDown(1, last); /* move last item to the proper place */ if (!this->IsEmpty()) this->data[gap] = last; + this->data.pop_back(); CHECK_CONSISTY(); return first; @@ -268,6 +247,8 @@ public: assert(index == this->items); this->items--; } + this->data.pop_back(); + CHECK_CONSISTY(); } @@ -281,13 +262,8 @@ public: */ inline size_t FindIndex(const T &item) const { - if (this->IsEmpty()) return 0; - for (T **ppI = this->data + 1, **ppLast = ppI + this->items; ppI <= ppLast; ppI++) { - if (*ppI == &item) { - return ppI - this->data; - } - } - return 0; + auto it = std::find(this->data.begin(), this->data.end(), &item); + return it == this->data.end() ? 0 : std::distance(this->data.begin(), it); } /** @@ -297,6 +273,9 @@ public: inline void Clear() { this->items = 0; + this->data.resize(1); + + CHECK_CONSISTY(); } };