32 #include <agrum/tools/core/heap.h> 37 template <
typename Val,
typename Cmp,
typename Alloc >
38 Heap< Val, Cmp, Alloc >::Heap(Cmp compare, Size capacity) : _cmp_(compare) {
39 _heap_.reserve(capacity);
41 GUM_CONSTRUCTOR(Heap);
45 template <
typename Val,
typename Cmp,
typename Alloc >
46 Heap< Val, Cmp, Alloc >::Heap(std::initializer_list< Val > list) {
47 _heap_.reserve(list.size());
48 for (
const auto& elt: list) {
52 GUM_CONSTRUCTOR(Heap);
56 template <
typename Val,
typename Cmp,
typename Alloc >
57 Heap< Val, Cmp, Alloc >::Heap(
const Heap< Val, Cmp, Alloc >& from) :
58 _heap_(from._heap_), _nb_elements_(from._nb_elements_), _cmp_(from._cmp_) {
64 template <
typename Val,
typename Cmp,
typename Alloc >
65 template <
typename OtherAlloc >
66 Heap< Val, Cmp, Alloc >::Heap(
const Heap< Val, Cmp, OtherAlloc >& from) :
67 _nb_elements_(from._nb_elements_), _cmp_(from._cmp_) {
68 _heap_.reserve(_nb_elements_);
71 for (
unsigned i = 0; i < _nb_elements_; ++i)
72 _heap_.push_back(from._heap_[i]);
79 template <
typename Val,
typename Cmp,
typename Alloc >
80 Heap< Val, Cmp, Alloc >::Heap(Heap< Val, Cmp, Alloc >&& from)
noexcept :
81 _heap_(std::move(from._heap_)), _nb_elements_(std::move(from._nb_elements_)),
82 _cmp_(std::move(from._cmp_)) {
88 template <
typename Val,
typename Cmp,
typename Alloc >
89 Heap< Val, Cmp, Alloc >::~Heap() {
95 template <
typename Val,
typename Cmp,
typename Alloc >
96 Heap< Val, Cmp, Alloc >& Heap< Val, Cmp, Alloc >::operator=(
const Heap< Val, Cmp, Alloc >& from) {
100 _heap_ = from._heap_;
110 _nb_elements_ = from._nb_elements_;
120 template <
typename Val,
typename Cmp,
typename Alloc >
121 template <
typename OtherAlloc >
122 Heap< Val, Cmp, Alloc >&
123 Heap< Val, Cmp, Alloc >::operator=(
const Heap< Val, Cmp, OtherAlloc >& from) {
129 if (_heap_.capacity() < from._nb_elements_) _heap_.reserve(from._nb_elements_);
131 for (
unsigned int i = 0; i < from._nb_elements_; ++i) {
132 _heap_.push_back(from._heap_[i]);
141 _nb_elements_ = from._nb_elements_;
151 template <
typename Val,
typename Cmp,
typename Alloc >
152 Heap< Val, Cmp, Alloc >&
153 Heap< Val, Cmp, Alloc >::operator=(Heap< Val, Cmp, Alloc >&& from)
noexcept {
156 _heap_ = std::move(from._heap_);
157 _nb_elements_ = std::move(from._nb_elements_);
158 _cmp_ = std::move(from._cmp_);
165 template <
typename Val,
typename Cmp,
typename Alloc >
166 INLINE
const Val& Heap< Val, Cmp, Alloc >::top()
const {
167 if (!_nb_elements_) { GUM_ERROR(NotFound,
"empty heap") }
173 template <
typename Val,
typename Cmp,
typename Alloc >
174 INLINE Size Heap< Val, Cmp, Alloc >::size()
const noexcept {
175 return _nb_elements_;
179 template <
typename Val,
typename Cmp,
typename Alloc >
180 INLINE Size Heap< Val, Cmp, Alloc >::capacity()
const noexcept {
181 return Size(_heap_.size());
185 template <
typename Val,
typename Cmp,
typename Alloc >
186 INLINE
void Heap< Val, Cmp, Alloc >::resize(Size new_size) {
187 if (new_size > _nb_elements_) _heap_.reserve(new_size);
191 template <
typename Val,
typename Cmp,
typename Alloc >
192 void Heap< Val, Cmp, Alloc >::eraseByPos(Size index) {
193 if (index >= _nb_elements_)
return;
196 Val last = std::move(_heap_[_nb_elements_ - 1]);
200 if (!_nb_elements_ || (index == _nb_elements_))
return;
205 for (Size j = (index << 1) + 1; j < _nb_elements_; i = j, j = (j << 1) + 1) {
207 if ((j + 1 < _nb_elements_) && _cmp_(_heap_[j + 1], _heap_[j])) ++j;
210 if (_cmp_(last, _heap_[j]))
break;
212 _heap_[i] = std::move(_heap_[j]);
215 _heap_[i] = std::move(last);
219 template <
typename Val,
typename Cmp,
typename Alloc >
220 INLINE
void Heap< Val, Cmp, Alloc >::erase(
const Val& val) {
222 for (Size i = 0; i < _nb_elements_; ++i)
223 if (_heap_[i] == val) {
230 template <
typename Val,
typename Cmp,
typename Alloc >
231 INLINE
void Heap< Val, Cmp, Alloc >::eraseTop() {
233 if (!_nb_elements_)
return;
238 template <
typename Val,
typename Cmp,
typename Alloc >
239 INLINE Val Heap< Val, Cmp, Alloc >::pop() {
240 if (!_nb_elements_) { GUM_ERROR(NotFound,
"empty heap") }
248 template <
typename Val,
typename Cmp,
typename Alloc >
249 Size Heap< Val, Cmp, Alloc >::_restoreHeap_() {
251 Size i = _nb_elements_ - 1;
252 Val v = std::move(_heap_[i]);
255 for (Size j = (i - 1) >> 1; i && _cmp_(v, _heap_[j]); i = j, j = (j - 1) >> 1)
256 _heap_[i] = std::move(_heap_[j]);
258 _heap_[i] = std::move(v);
264 template <
typename Val,
typename Cmp,
typename Alloc >
265 INLINE Size Heap< Val, Cmp, Alloc >::insert(
const Val& val) {
267 _heap_.push_back(val);
269 return _restoreHeap_();
273 template <
typename Val,
typename Cmp,
typename Alloc >
274 Size Heap< Val, Cmp, Alloc >::insert(Val&& val) {
276 _heap_.push_back(std::move(val));
278 return _restoreHeap_();
282 template <
typename Val,
typename Cmp,
typename Alloc >
283 template <
typename... Args >
284 Size Heap< Val, Cmp, Alloc >::emplace(Args&&... args) {
286 _heap_.emplace_back(std::forward< Args >(args)...);
288 return _restoreHeap_();
292 template <
typename Val,
typename Cmp,
typename Alloc >
293 INLINE
bool Heap< Val, Cmp, Alloc >::empty()
const noexcept {
294 return (_nb_elements_ == 0);
298 template <
typename Val,
typename Cmp,
typename Alloc >
299 INLINE
bool Heap< Val, Cmp, Alloc >::contains(
const Val& val)
const {
300 for (Size i = 0; i < _nb_elements_; ++i)
301 if (_heap_[i] == val)
return true;
307 template <
typename Val,
typename Cmp,
typename Alloc >
308 INLINE
const Val& Heap< Val, Cmp, Alloc >::operator[](Size index)
const {
310 if (index >= _nb_elements_) { GUM_ERROR(NotFound,
"not enough elements in the heap") }
312 return _heap_[index];
316 template <
typename Val,
typename Cmp,
typename Alloc >
317 std::string Heap< Val, Cmp, Alloc >::toString()
const {
319 std::stringstream stream;
322 for (Size i = 0; i != _nb_elements_; ++i, deja =
true) {
323 if (deja) stream <<
" , ";
334 template <
typename Val,
typename Cmp,
typename Alloc >
335 INLINE std::ostream& operator<<(std::ostream& stream,
const Heap< Val, Cmp, Alloc >& heap) {
336 stream << heap.toString();