aGrUM  0.20.3
a C++ library for (probabilistic) graphical models
priorityQueue_tpl.h
Go to the documentation of this file.
1 /**
2  *
3  * Copyright (c) 2005-2021 by Pierre-Henri WUILLEMIN(@LIP6) & Christophe GONZALES(@AMU)
4  * info_at_agrum_dot_org
5  *
6  * This library is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this library. If not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 
22 /**
23  * @file
24  * @brief template implementations of priority queues
25  *
26  * @author Christophe GONZALES(@AMU) and Pierre-Henri WUILLEMIN(@LIP6)
27  */
28 
29 #include <agrum/tools/core/priorityQueue.h>
30 
31 namespace gum {
32 
33  // ===========================================================================
34  // === GENERAL IMPLEMENTATIION OF PRIORITY QUEUES ===
35  // ===========================================================================
36 
37  // basic constructor
38  template < typename Val, typename Priority, typename Cmp, typename Alloc, bool Gen >
39  INLINE PriorityQueueImplementation< Val, Priority, Cmp, Alloc, Gen >::PriorityQueueImplementation(
40  Cmp compare,
41  Size capacity) :
42  _indices_(capacity >> 1, true, true),
43  _cmp_(compare) {
45 
47  }
48 
49  // initializer list constructor
50  template < typename Val, typename Priority, typename Cmp, typename Alloc, bool Gen >
53  _indices_(Size(list.size()) / 2, true, true) {
54  // fill the queue
56  for (const auto& elt: list) {
58  }
59 
61  }
62 
63  // copy constructor
64  template < typename Val, typename Priority, typename Cmp, typename Alloc, bool Gen >
69  // fill the heap structure
70  for (const auto& elt: _indices_) {
72  }
73 
75  }
76 
77  // generalized copy constructor
78  template < typename Val, typename Priority, typename Cmp, typename Alloc, bool Gen >
79  template < typename OtherAlloc >
84  // fill the heap structure
85  if (_nb_elements_) {
87  for (const auto& elt: from._heap_) {
89  }
90  for (const auto& elt: _indices_) {
92  }
93  }
94 
96  }
97 
98  // move constructor
99  template < typename Val, typename Priority, typename Cmp, typename Alloc, bool Gen >
104  _cmp_(std::move(from._cmp_)) {
106  }
107 
108  // destructor
109  template < typename Val, typename Priority, typename Cmp, typename Alloc, bool Gen >
112  }
113 
114  // copy operator
115  template < typename Val, typename Priority, typename Cmp, typename Alloc, bool Gen >
119  // avoid self assignment
120  if (this != &from) {
122 
123  try {
124  // set the comparison function
125  _cmp_ = from._cmp_;
126 
127  // copy the indices and the heap
129  _heap_ = from._heap_;
131 
132  // restore the link between _indices_ and _heap_
133  for (const auto& elt: _indices_) {
135  }
136  } catch (...) {
137  _heap_.clear();
138  _indices_.clear();
139  _nb_elements_ = 0;
140 
141  throw;
142  }
143  }
144 
145  return *this;
146  }
147 
148  // generalized copy operator
149  template < typename Val, typename Priority, typename Cmp, typename Alloc, bool Gen >
150  template < typename OtherAlloc >
155 
156  try {
157  // set the comprison function
158  _cmp_ = from._cmp_;
159 
160  // copy the indices and the heap
163 
164  _heap_.clear();
165  if (_nb_elements_) {
167  for (const auto& elt: from._heap_) {
169  }
170  for (const auto& elt: _indices_) {
172  }
173  }
174  } catch (...) {
175  _heap_.clear();
176  _indices_.clear();
177  _nb_elements_ = 0;
178 
179  throw;
180  }
181 
182  return *this;
183  }
184 
185  // move operator
186  template < typename Val, typename Priority, typename Cmp, typename Alloc, bool Gen >
190  // avoid self assignment
191  if (this != &from) {
193 
195  _heap_ = std::move(from._heap_);
196  _cmp_ = std::move(from._cmp_);
198  }
199 
200  return *this;
201  }
202 
203  // returns the element at the top of the priority queue
204  template < typename Val, typename Priority, typename Cmp, typename Alloc, bool Gen >
206  if (!_nb_elements_) { GUM_ERROR(NotFound, "empty priority queue") }
207 
208  return *(_heap_[0].second);
209  }
210 
211  // returns the priority of the top element
212  template < typename Val, typename Priority, typename Cmp, typename Alloc, bool Gen >
213  INLINE const Priority&
215  if (!_nb_elements_) { GUM_ERROR(NotFound, "empty priority queue") }
216 
217  return _heap_[0].first;
218  }
219 
220  // returns the number of elements in the priority queue
221  template < typename Val, typename Priority, typename Cmp, typename Alloc, bool Gen >
223  return _nb_elements_;
224  }
225 
226  // return the size of the array storing the priority queue
227  template < typename Val, typename Priority, typename Cmp, typename Alloc, bool Gen >
228  INLINE Size
230  return Size(_heap_.capacity());
231  }
232 
233  // changes the size of the array storing the priority queue
234  template < typename Val, typename Priority, typename Cmp, typename Alloc, bool Gen >
236  if (new_size < _nb_elements_) return;
237 
240  }
241 
242  // removes all the elements from the queue
243  template < typename Val, typename Priority, typename Cmp, typename Alloc, bool Gen >
245  _nb_elements_ = 0;
246  _heap_.clear();
247  _indices_.clear();
248  }
249 
250  // removes the element at index elt from the priority queue
251  template < typename Val, typename Priority, typename Cmp, typename Alloc, bool Gen >
253  if (index >= _nb_elements_) return;
254 
255  // remove the element from the hashtable
257 
258  // put the last element at the "index" location
259  std::pair< Priority, const Val* > last = std::move(_heap_[_nb_elements_ - 1]);
260  _heap_.pop_back();
261  --_nb_elements_;
262 
263  if (!_nb_elements_ || (index == _nb_elements_)) return;
264 
265  // restore the heap property
266  Size i = index;
267 
268  for (Size j = (index << 1) + 1; j < _nb_elements_; i = j, j = (j << 1) + 1) {
269  // let j be the max child
270  if ((j + 1 < _nb_elements_) && _cmp_(_heap_[j + 1].first, _heap_[j].first)) ++j;
271 
272  // if "last" is lower than heap[j], "last" must be stored at index i
273  if (_cmp_(last.first, _heap_[j].first)) break;
274 
275  // else pull up the jth node
276  _heap_[i] = std::move(_heap_[j]);
277  _indices_[*(_heap_[i].second)] = i;
278  }
279 
280  // put "last" back into the heap
281  _heap_[i] = std::move(last);
282  _indices_[*(_heap_[i].second)] = i;
283  }
284 
285  // removes a given element from the priority queue (but does not return it)
286  template < typename Val, typename Priority, typename Cmp, typename Alloc, bool Gen >
288  try {
290  } catch (NotFound&) {}
291  }
292 
293  // removes the top of the priority queue (but does not return it)
294  template < typename Val, typename Priority, typename Cmp, typename Alloc, bool Gen >
296  eraseByPos(0);
297  }
298 
299  // removes the top element from the priority queue and return it
300  template < typename Val, typename Priority, typename Cmp, typename Alloc, bool Gen >
302  if (!_nb_elements_) { GUM_ERROR(NotFound, "empty priority queue") }
303 
304  Val v = *(_heap_[0].second);
305  eraseByPos(0);
306 
307  return v;
308  }
309 
310  // returns a hashtable the keys of which are the values stored in the queue
311  template < typename Val, typename Priority, typename Cmp, typename Alloc, bool Gen >
312  INLINE const HashTable< Val, Size >&
314  return reinterpret_cast< const HashTable< Val, Size >& >(_indices_);
315  }
316 
317  // inserts a new (a copy) element in the priority queue
318  template < typename Val, typename Priority, typename Cmp, typename Alloc, bool Gen >
320  const Val& val,
321  const Priority& priority) {
322  // create the entry in the indices hashtable (if the element already exists,
323  // _indices_.insert will raise a Duplicateelement exception)
325 
326  try {
328  } catch (...) {
330  throw;
331  }
332 
334  ++_nb_elements_;
335 
336  // restore the heap property
337  Size i = _nb_elements_ - 1;
338 
339  for (Size j = (i - 1) >> 1; i && _cmp_(new_heap_val.first, _heap_[j].first);
340  i = j, j = (j - 1) >> 1) {
341  _heap_[i] = std::move(_heap_[j]);
342  _indices_[*(_heap_[i].second)] = i;
343  }
344 
345  // put the new bucket into the heap
347  _heap_[i].second = &(new_elt.first);
348  new_elt.second = i;
349 
350  return i;
351  }
352 
353  // inserts by move a new element in the priority queue
354  template < typename Val, typename Priority, typename Cmp, typename Alloc, bool Gen >
355  INLINE Size
357  Priority&& priority) {
358  // create the entry in the indices hashtable (if the element already exists,
359  // _indices_.insert will raise a Duplicateelement exception)
361  = _indices_.insert(std::move(val), 0);
362 
363  try {
365  } catch (...) {
367  throw;
368  }
369 
371  ++_nb_elements_;
372 
373  // restore the heap property
374  Size i = _nb_elements_ - 1;
375 
376  for (Size j = (i - 1) >> 1; i && _cmp_(new_heap_val.first, _heap_[j].first);
377  i = j, j = (j - 1) >> 1) {
378  _heap_[i] = std::move(_heap_[j]);
379  _indices_[*(_heap_[i].second)] = i;
380  }
381 
382  // put the new bucket into the heap
384  _heap_[i].second = &(new_elt.first);
385  new_elt.second = i;
386 
387  return i;
388  }
389 
390  // emplace a new element into the priority queue
391  template < typename Val, typename Priority, typename Cmp, typename Alloc, bool Gen >
392  template < typename... Args >
393  INLINE Size
396  = std::make_pair< Val, Priority >(std::forward< Args >(args)...);
398  }
399 
400  // indicates whether the priority queue is empty
401  template < typename Val, typename Priority, typename Cmp, typename Alloc, bool Gen >
402  INLINE bool
404  return (_nb_elements_ == 0);
405  }
406 
407  // indicates whether the priority queue contains a given value
408  template < typename Val, typename Priority, typename Cmp, typename Alloc, bool Gen >
409  INLINE bool
411  return _indices_.exists(val);
412  }
413 
414  // returns the element at position "index" in the priority queue
415  template < typename Val, typename Priority, typename Cmp, typename Alloc, bool Gen >
416  INLINE const Val&
418  if (index >= _nb_elements_) {
419  GUM_ERROR(NotFound, "not enough elements in the PriorityQueueImplementation")
420  }
421 
422  return *(_heap_[index].second);
423  }
424 
425  // displays the content of the queue
426  template < typename Val, typename Priority, typename Cmp, typename Alloc, bool Gen >
428  bool deja = false;
430  stream << "[";
431 
432  for (Size i = 0; i != _nb_elements_; ++i, deja = true) {
433  if (deja) stream << " , ";
434 
435  stream << "(" << _heap_[i].first << " , " << *(_heap_[i].second) << ")";
436  }
437 
438  stream << "]";
439 
440  return stream.str();
441  }
442 
443  // changes the size of the internal structure storing the priority queue
444  template < typename Val, typename Priority, typename Cmp, typename Alloc, bool Gen >
446  Size index,
447  const Priority& new_priority) {
448  // check whether the element the priority of which should be changed exists
449  if (index >= _nb_elements_) {
450  GUM_ERROR(NotFound, "not enough elements in the PriorityQueueImplementation")
451  }
452 
453  // get the element itself
454  const Val* val = _heap_[index].second;
455 
456  // restore the heap property
457  Size i = index;
458 
459  // move val upward if needed
460  for (Size j = (i - 1) >> 1; i && _cmp_(new_priority, _heap_[j].first);
461  i = j, j = (j - 1) >> 1) {
462  _heap_[i] = std::move(_heap_[j]);
463  _indices_[*(_heap_[i].second)] = i;
464  }
465 
466  // move val downward if needed
467  for (Size j = (i << 1) + 1; j < _nb_elements_; i = j, j = (j << 1) + 1) {
468  // let j be the max child
469  if ((j + 1 < _nb_elements_) && _cmp_(_heap_[j + 1].first, _heap_[j].first)) ++j;
470 
471  // if "val" is lower than heap[j], "val" must be stored at index i
472  if (_cmp_(new_priority, _heap_[j].first)) break;
473 
474  // else pull up the jth node
475  _heap_[i] = std::move(_heap_[j]);
476  _indices_[*(_heap_[i].second)] = i;
477  }
478 
479  // update the index of val
481  _heap_[i].second = val;
482  _indices_[*val] = i;
483 
484  return i;
485  }
486 
487  // changes the size of the internal structure storing the priority queue
488  template < typename Val, typename Priority, typename Cmp, typename Alloc, bool Gen >
490  Size index,
492  // check whether the element the priority of which should be changed exists
493  if (index >= _nb_elements_) {
494  GUM_ERROR(NotFound, "not enough elements in the PriorityQueueImplementation")
495  }
496 
497  // get the element itself
498  const Val* val = _heap_[index].second;
499 
500  // restore the heap property
501  Size i = index;
502 
503  // move val upward if needed
504  for (Size j = (i - 1) >> 1; i && _cmp_(new_priority, _heap_[j].first);
505  i = j, j = (j - 1) >> 1) {
506  _heap_[i] = std::move(_heap_[j]);
507  _indices_[*(_heap_[i].second)] = i;
508  }
509 
510  // move val downward if needed
511  for (Size j = (i << 1) + 1; j < _nb_elements_; i = j, j = (j << 1) + 1) {
512  // let j be the max child
513  if ((j + 1 < _nb_elements_) && _cmp_(_heap_[j + 1].first, _heap_[j].first)) ++j;
514 
515  // if "val" is lower than heap[j], "val" must be stored at index i
516  if (_cmp_(new_priority, _heap_[j].first)) break;
517 
518  // else pull up the jth node
519  _heap_[i] = std::move(_heap_[j]);
520  _indices_[*(_heap_[i].second)] = i;
521  }
522 
523  // update the index of val
525  _heap_[i].second = val;
526  _indices_[*val] = i;
527 
528  return i;
529  }
530 
531  // modifies the priority of a given element
532  template < typename Val, typename Priority, typename Cmp, typename Alloc, bool Gen >
534  const Val& elt,
535  const Priority& new_priority) {
537  }
538 
539  // modifies the priority of a given element
540  template < typename Val, typename Priority, typename Cmp, typename Alloc, bool Gen >
542  const Val& elt,
545  }
546 
547  // returns the priority of a given element
548  template < typename Val, typename Priority, typename Cmp, typename Alloc, bool Gen >
549  INLINE const Priority&
551  return _heap_[_indices_[elt]].first;
552  }
553 
554  // returns the priority of a given element
555  template < typename Val, typename Priority, typename Cmp, typename Alloc, bool Gen >
556  INLINE const Priority&
558  Size index) const {
559  if (index > _nb_elements_) {
560  GUM_ERROR(NotFound, "not enough elements in the PriorityQueueImplementation")
561  }
562  return _heap_[index].first;
563  }
564 
565  // ===========================================================================
566  // === SCALAR OPTIMIZED IMPLEMENTATION OF PRIORITY QUEUES ===
567  // ===========================================================================
568 
569  // basic constructor
570  template < typename Val, typename Priority, typename Cmp, typename Alloc >
571  INLINE
573  Cmp compare,
574  Size capacity) :
575  _indices_(capacity >> 1, true, true),
576  _cmp_(compare) {
578 
579  // for debugging purposes
581  }
582 
583  // initializer list constructor
584  template < typename Val, typename Priority, typename Cmp, typename Alloc >
587  _indices_(Size(list.size()) / 2, true, true) {
588  // fill the queue
589  _heap_.reserve(list.size());
590  for (const auto& elt: list) {
592  }
593 
594  // for debugging purposes
596  }
597 
598  // copy constructor
599  template < typename Val, typename Priority, typename Cmp, typename Alloc >
601  const PriorityQueueImplementation< Val, Priority, Cmp, Alloc, true >& from) :
602  _heap_(from._heap_),
604  // for debugging purposes
606  }
607 
608  // generalized copy constructor
609  template < typename Val, typename Priority, typename Cmp, typename Alloc >
610  template < typename OtherAlloc >
615  // fill the heap structure
616  if (_nb_elements_) {
618  for (const auto& elt: from._heap_) {
620  }
621  }
622 
623  // for debugging purposes
625  }
626 
627  // move constructor
628  template < typename Val, typename Priority, typename Cmp, typename Alloc >
633  _cmp_(std::move(from._cmp_)) {
634  // for debugging purposes
636  }
637 
638  // destructor
639  template < typename Val, typename Priority, typename Cmp, typename Alloc >
641  // for debugging purposes
643  }
644 
645  // copy operator
646  template < typename Val, typename Priority, typename Cmp, typename Alloc >
649  const PriorityQueueImplementation< Val, Priority, Cmp, Alloc, true >& from) {
650  // avoid self assignment
651  if (this != &from) {
652  // for debugging purposes
654 
655  try {
656  // set the comparison function
657  _cmp_ = from._cmp_;
658 
659  // copy the indices and the heap
661  _heap_ = from._heap_;
663  } catch (...) {
664  _heap_.clear();
665  _indices_.clear();
666  _nb_elements_ = 0;
667 
668  throw;
669  }
670  }
671 
672  return *this;
673  }
674 
675  // generalized copy operator
676  template < typename Val, typename Priority, typename Cmp, typename Alloc >
677  template < typename OtherAlloc >
681  // for debugging purposes
683 
684  try {
685  // set the comprison function
686  _cmp_ = from._cmp_;
687 
688  // copy the indices and the heap
691 
692  _heap_.clear();
693  if (_nb_elements_) {
695  for (const auto& elt: from._heap_) {
697  }
698  }
699  } catch (...) {
700  _heap_.clear();
701  _indices_.clear();
702  _nb_elements_ = 0;
703 
704  throw;
705  }
706 
707  return *this;
708  }
709 
710  // move operator
711  template < typename Val, typename Priority, typename Cmp, typename Alloc >
715  // avoid self assignment
716  if (this != &from) {
717  // for debugging purposes
719 
721  _heap_ = std::move(from._heap_);
722  _cmp_ = std::move(from._cmp_);
724  }
725 
726  return *this;
727  }
728 
729  // returns the element at the top of the priority queue
730  template < typename Val, typename Priority, typename Cmp, typename Alloc >
731  INLINE const Val& PriorityQueueImplementation< Val, Priority, Cmp, Alloc, true >::top() const {
732  if (!_nb_elements_) { GUM_ERROR(NotFound, "empty priority queue") }
733 
734  return _heap_[0].second;
735  }
736 
737  // returns the priority of the top element
738  template < typename Val, typename Priority, typename Cmp, typename Alloc >
739  INLINE const Priority&
741  if (!_nb_elements_) { GUM_ERROR(NotFound, "empty priority queue") }
742 
743  return _heap_[0].first;
744  }
745 
746  // returns the number of elements in the priority queue
747  template < typename Val, typename Priority, typename Cmp, typename Alloc >
748  INLINE Size
749  PriorityQueueImplementation< Val, Priority, Cmp, Alloc, true >::size() const noexcept {
750  return _nb_elements_;
751  }
752 
753  // return the size of the array storing the priority queue
754  template < typename Val, typename Priority, typename Cmp, typename Alloc >
755  INLINE Size
756  PriorityQueueImplementation< Val, Priority, Cmp, Alloc, true >::capacity() const noexcept {
757  return Size(_heap_.capacity());
758  }
759 
760  // changes the size of the array storing the priority queue
761  template < typename Val, typename Priority, typename Cmp, typename Alloc >
762  INLINE void
764  if (new_size < _nb_elements_) return;
765 
768  }
769 
770  // removes all the elements from the queue
771  template < typename Val, typename Priority, typename Cmp, typename Alloc >
773  _nb_elements_ = 0;
774  _heap_.clear();
775  _indices_.clear();
776  }
777 
778  // removes the element at index elt from the priority queue
779  template < typename Val, typename Priority, typename Cmp, typename Alloc >
781  if (index >= _nb_elements_) return;
782 
783  // remove the element from the hashtable
785 
786  // put the last element at the "index" location
788  _heap_.pop_back();
789  --_nb_elements_;
790 
791  if (!_nb_elements_ || (index == _nb_elements_)) return;
792 
793  // restore the heap property
794  Size i = index;
795 
796  for (Size j = (index << 1) + 1; j < _nb_elements_; i = j, j = (j << 1) + 1) {
797  // let j be the max child
798  if ((j + 1 < _nb_elements_) && _cmp_(_heap_[j + 1].first, _heap_[j].first)) ++j;
799 
800  // if "last" is lower than heap[j], "last" must be stored at index i
801  if (_cmp_(last.first, _heap_[j].first)) break;
802 
803  // else pull up the jth node
804  _heap_[i] = std::move(_heap_[j]);
805  _indices_[_heap_[i].second] = i;
806  }
807 
808  // put "last" back into the heap
809  _heap_[i] = std::move(last);
810  _indices_[_heap_[i].second] = i;
811  }
812 
813  // removes a given element from the priority queue (but does not return it)
814  template < typename Val, typename Priority, typename Cmp, typename Alloc >
816  try {
818  } catch (NotFound&) {}
819  }
820 
821  // removes the top of the priority queue (but does not return it)
822  template < typename Val, typename Priority, typename Cmp, typename Alloc >
824  eraseByPos(0);
825  }
826 
827  // removes the top element from the priority queue and return it
828  template < typename Val, typename Priority, typename Cmp, typename Alloc >
830  if (!_nb_elements_) { GUM_ERROR(NotFound, "empty priority queue") }
831 
832  Val v = _heap_[0].second;
833  eraseByPos(0);
834 
835  return v;
836  }
837 
838  // returns a hashtable the keys of which are the values stored in the queue
839  template < typename Val, typename Priority, typename Cmp, typename Alloc >
840  INLINE const HashTable< Val, Size >&
841  PriorityQueueImplementation< Val, Priority, Cmp, Alloc, true >::allValues() const noexcept {
842  return reinterpret_cast< const HashTable< Val, Size >& >(_indices_);
843  }
844 
845  // inserts a new (a copy) element in the priority queue
846  template < typename Val, typename Priority, typename Cmp, typename Alloc >
848  Val val,
849  const Priority& priority) {
850  // create the entry in the indices hashtable (if the element already exists,
851  // _indices_.insert will raise a Duplicateelement exception)
853 
854  try {
856  } catch (...) {
858  throw;
859  }
860 
862  ++_nb_elements_;
863 
864  // restore the heap property
865  Size i = _nb_elements_ - 1;
866 
867  for (Size j = (i - 1) >> 1; i && _cmp_(new_heap_val.first, _heap_[j].first);
868  i = j, j = (j - 1) >> 1) {
869  _heap_[i] = std::move(_heap_[j]);
870  _indices_[_heap_[i].second] = i;
871  }
872 
873  // put the new bucket into the heap
875  _heap_[i].second = val;
876  new_elt.second = i;
877 
878  return i;
879  }
880 
881  // inserts by move a new element in the priority queue
882  template < typename Val, typename Priority, typename Cmp, typename Alloc >
883  INLINE Size
885  Priority&& priority) {
886  // create the entry in the indices hashtable (if the element already exists,
887  // _indices_.insert will raise a Duplicateelement exception)
889 
890  try {
892  } catch (...) {
894  throw;
895  }
896 
898  ++_nb_elements_;
899 
900  // restore the heap property
901  Size i = _nb_elements_ - 1;
902 
903  for (Size j = (i - 1) >> 1; i && _cmp_(new_heap_val.first, _heap_[j].first);
904  i = j, j = (j - 1) >> 1) {
905  _heap_[i] = std::move(_heap_[j]);
906  _indices_[_heap_[i].second] = i;
907  }
908 
909  // put the new bucket into the heap
911  _heap_[i].second = val;
912  new_elt.second = i;
913 
914  return i;
915  }
916 
917  // emplace a new element into the priority queue
918  template < typename Val, typename Priority, typename Cmp, typename Alloc >
919  template < typename... Args >
920  INLINE Size
923  = std::make_pair< Val, Priority >(std::forward< Args >(args)...);
925  }
926 
927  // indicates whether the priority queue is empty
928  template < typename Val, typename Priority, typename Cmp, typename Alloc >
929  INLINE bool
930  PriorityQueueImplementation< Val, Priority, Cmp, Alloc, true >::empty() const noexcept {
931  return (_nb_elements_ == 0);
932  }
933 
934  // indicates whether the priority queue contains a given value
935  template < typename Val, typename Priority, typename Cmp, typename Alloc >
936  INLINE bool
938  return _indices_.exists(val);
939  }
940 
941  // returns the element at position "index" in the priority queue
942  template < typename Val, typename Priority, typename Cmp, typename Alloc >
943  INLINE const Val&
945  if (index >= _nb_elements_) {
946  GUM_ERROR(NotFound, "not enough elements in the PriorityQueueImplementation")
947  }
948 
949  return _heap_[index].second;
950  }
951 
952  // displays the content of the queue
953  template < typename Val, typename Priority, typename Cmp, typename Alloc >
955  bool deja = false;
957  stream << "[";
958 
959  for (Size i = 0; i != _nb_elements_; ++i, deja = true) {
960  if (deja) stream << " , ";
961 
962  stream << "(" << _heap_[i].first << " , " << _heap_[i].second << ")";
963  }
964 
965  stream << "]";
966 
967  return stream.str();
968  }
969 
970  // changes the size of the internal structure storing the priority queue
971  template < typename Val, typename Priority, typename Cmp, typename Alloc >
973  Size index,
974  const Priority& new_priority) {
975  // check whether the element the priority of which should be changed exists
976  if (index >= _nb_elements_) {
977  GUM_ERROR(NotFound, "not enough elements in the PriorityQueueImplementation")
978  }
979 
980  // get the element itself
982 
983  // restore the heap property
984  Size i = index;
985 
986  // move val upward if needed
987  for (Size j = (i - 1) >> 1; i && _cmp_(new_priority, _heap_[j].first);
988  i = j, j = (j - 1) >> 1) {
989  _heap_[i] = std::move(_heap_[j]);
990  _indices_[_heap_[i].second] = i;
991  }
992 
993  // move val downward if needed
994  for (Size j = (i << 1) + 1; j < _nb_elements_; i = j, j = (j << 1) + 1) {
995  // let j be the max child
996  if ((j + 1 < _nb_elements_) && _cmp_(_heap_[j + 1].first, _heap_[j].first)) ++j;
997 
998  // if "val" is lower than heap[j], "val" must be stored at index i
999  if (_cmp_(new_priority, _heap_[j].first)) break;
1000 
1001  // else pull up the jth node
1002  _heap_[i] = std::move(_heap_[j]);
1003  _indices_[_heap_[i].second] = i;
1004  }
1005 
1006  // update the index of val
1008  _heap_[i].second = val;
1009  _indices_[val] = i;
1010 
1011  return i;
1012  }
1013 
1014  // changes the size of the internal structure storing the priority queue
1015  template < typename Val, typename Priority, typename Cmp, typename Alloc >
1017  Size index,
1018  Priority&& new_priority) {
1019  // check whether the element the priority of which should be changed exists
1020  if (index >= _nb_elements_) {
1021  GUM_ERROR(NotFound, "not enough elements in the PriorityQueueImplementation")
1022  }
1023 
1024  // get the element itself
1025  Val val = _heap_[index].second;
1026 
1027  // restore the heap property
1028  Size i = index;
1029 
1030  // move val upward if needed
1031  for (Size j = (i - 1) >> 1; i && _cmp_(new_priority, _heap_[j].first);
1032  i = j, j = (j - 1) >> 1) {
1033  _heap_[i] = std::move(_heap_[j]);
1034  _indices_[_heap_[i].second] = i;
1035  }
1036 
1037  // move val downward if needed
1038  for (Size j = (i << 1) + 1; j < _nb_elements_; i = j, j = (j << 1) + 1) {
1039  // let j be the max child
1040  if ((j + 1 < _nb_elements_) && _cmp_(_heap_[j + 1].first, _heap_[j].first)) ++j;
1041 
1042  // if "val" is lower than heap[j], "val" must be stored at index i
1043  if (_cmp_(new_priority, _heap_[j].first)) break;
1044 
1045  // else pull up the jth node
1046  _heap_[i] = std::move(_heap_[j]);
1047  _indices_[_heap_[i].second] = i;
1048  }
1049 
1050  // update the index of val
1052  _heap_[i].second = val;
1053  _indices_[val] = i;
1054 
1055  return i;
1056  }
1057 
1058  // modifies the priority of a given element
1059  template < typename Val, typename Priority, typename Cmp, typename Alloc >
1061  Val elt,
1062  const Priority& new_priority) {
1064  }
1065 
1066  // modifies the priority of a given element
1067  template < typename Val, typename Priority, typename Cmp, typename Alloc >
1069  Val elt,
1070  Priority&& new_priority) {
1072  }
1073 
1074  // returns the priority of a given element
1075  template < typename Val, typename Priority, typename Cmp, typename Alloc >
1076  INLINE const Priority&
1078  return _heap_[_indices_[elt]].first;
1079  }
1080 
1081  // returns the priority of a given element
1082  template < typename Val, typename Priority, typename Cmp, typename Alloc >
1083  INLINE const Priority&
1085  Size index) const {
1086  if (index > _nb_elements_) {
1087  GUM_ERROR(NotFound, "not enough elements in the PriorityQueueImplementation")
1088  }
1089  return _heap_[index].first;
1090  }
1091 
1092  // ===========================================================================
1093  // === PRIORITY QUEUES ===
1094  // ===========================================================================
1095 
1096  // basic constructor
1097  template < typename Val, typename Priority, typename Cmp, typename Alloc >
1100  // for debugging purposes
1102  }
1103 
1104  // initializer list constructor
1105  template < typename Val, typename Priority, typename Cmp, typename Alloc >
1109  // for debugging purposes
1111  }
1112 
1113  // copy constructor
1114  template < typename Val, typename Priority, typename Cmp, typename Alloc >
1116  const PriorityQueue< Val, Priority, Cmp, Alloc >& from) :
1118  // for debugging purposes
1120  }
1121 
1122  // generalized copy constructor
1123  template < typename Val, typename Priority, typename Cmp, typename Alloc >
1124  template < typename OtherAlloc >
1126  const PriorityQueue< Val, Priority, Cmp, OtherAlloc >& from) :
1128  // for debugging purposes
1130  }
1131 
1132  // move constructor
1133  template < typename Val, typename Priority, typename Cmp, typename Alloc >
1135  PriorityQueue< Val, Priority, Cmp, Alloc >&& from) :
1137  // for debugging purposes
1139  }
1140 
1141  // destructor
1142  template < typename Val, typename Priority, typename Cmp, typename Alloc >
1144  // for debugging purposes
1146  }
1147 
1148  // copy operator
1149  template < typename Val, typename Priority, typename Cmp, typename Alloc >
1152  const PriorityQueue< Val, Priority, Cmp, Alloc >& from) {
1154  return *this;
1155  }
1156 
1157  // generalized copy operator
1158  template < typename Val, typename Priority, typename Cmp, typename Alloc >
1159  template < typename OtherAlloc >
1162  const PriorityQueue< Val, Priority, Cmp, OtherAlloc >& from) {
1164  return *this;
1165  }
1166 
1167  // move operator
1168  template < typename Val, typename Priority, typename Cmp, typename Alloc >
1171  PriorityQueue< Val, Priority, Cmp, Alloc >&& from) {
1173  return *this;
1174  }
1175 
1176  // A \c << operator for priority queues
1177  template < typename Val, typename Priority, typename Cmp, typename Alloc >
1179  const PriorityQueue< Val, Priority, Cmp, Alloc >& queue) {
1180  stream << queue.toString();
1181  return stream;
1182  }
1183 
1184 } /* namespace gum */
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:643