aGrUM  0.20.2
a C++ library for (probabilistic) graphical models
priorityQueue_tpl.h
Go to the documentation of this file.
1 /**
2  *
3  * Copyright 2005-2020 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,
39  typename Priority,
40  typename Cmp,
41  typename Alloc,
42  bool Gen >
43  INLINE PriorityQueueImplementation< Val, Priority, Cmp, Alloc, Gen >::
45  indices__(capacity >> 1, true, true),
46  cmp__(compare) {
48 
49  // for debugging purposes
51  }
52 
53  // initializer list constructor
54  template < typename Val,
55  typename Priority,
56  typename Cmp,
57  typename Alloc,
58  bool Gen >
62  indices__(Size(list.size()) / 2, true, true) {
63  // fill the queue
65  for (const auto& elt: list) {
67  }
68 
69  // for debugging purposes
71  }
72 
73  // copy constructor
74  template < typename Val,
75  typename Priority,
76  typename Cmp,
77  typename Alloc,
78  bool Gen >
82  from) :
85  cmp__(from.cmp__) {
86  // fill the heap structure
87  for (const auto& elt: indices__) {
89  }
90 
91  // for debugging purposes
93  }
94 
95  // generalized copy constructor
96  template < typename Val,
97  typename Priority,
98  typename Cmp,
99  typename Alloc,
100  bool Gen >
101  template < typename OtherAlloc >
105  from) :
108  // fill the heap structure
109  if (nb_elements__) {
111  for (const auto& elt: from.heap__) {
113  }
114  for (const auto& elt: indices__) {
116  }
117  }
118 
119  // for debugging purposes
121  }
122 
123  // move constructor
124  template < typename Val,
125  typename Priority,
126  typename Cmp,
127  typename Alloc,
128  bool Gen >
135  // for debugging purposes
137  }
138 
139  // destructor
140  template < typename Val,
141  typename Priority,
142  typename Cmp,
143  typename Alloc,
144  bool Gen >
147  // for debugging purposes
149  }
150 
151  // copy operator
152  template < typename Val,
153  typename Priority,
154  typename Cmp,
155  typename Alloc,
156  bool Gen >
160  from) {
161  // avoid self assignment
162  if (this != &from) {
163  // for debugging purposes
165 
166  try {
167  // set the comparison function
168  cmp__ = from.cmp__;
169 
170  // copy the indices and the heap
172  heap__ = from.heap__;
174 
175  // restore the link between indices__ and heap__
176  for (const auto& elt: indices__) {
178  }
179  } catch (...) {
180  heap__.clear();
181  indices__.clear();
182  nb_elements__ = 0;
183 
184  throw;
185  }
186  }
187 
188  return *this;
189  }
190 
191  // generalized copy operator
192  template < typename Val,
193  typename Priority,
194  typename Cmp,
195  typename Alloc,
196  bool Gen >
197  template < typename OtherAlloc >
201  from) {
202  // for debugging purposes
204 
205  try {
206  // set the comprison function
207  cmp__ = from.cmp__;
208 
209  // copy the indices and the heap
212 
213  heap__.clear();
214  if (nb_elements__) {
216  for (const auto& elt: from.heap__) {
218  }
219  for (const auto& elt: indices__) {
221  }
222  }
223  } catch (...) {
224  heap__.clear();
225  indices__.clear();
226  nb_elements__ = 0;
227 
228  throw;
229  }
230 
231  return *this;
232  }
233 
234  // move operator
235  template < typename Val,
236  typename Priority,
237  typename Cmp,
238  typename Alloc,
239  bool Gen >
243  // avoid self assignment
244  if (this != &from) {
245  // for debugging purposes
247 
249  heap__ = std::move(from.heap__);
250  cmp__ = std::move(from.cmp__);
252  }
253 
254  return *this;
255  }
256 
257  // returns the element at the top of the priority queue
258  template < typename Val,
259  typename Priority,
260  typename Cmp,
261  typename Alloc,
262  bool Gen >
263  INLINE const Val&
265  if (!nb_elements__) { GUM_ERROR(NotFound, "empty priority queue"); }
266 
267  return *(heap__[0].second);
268  }
269 
270  // returns the priority of the top element
271  template < typename Val,
272  typename Priority,
273  typename Cmp,
274  typename Alloc,
275  bool Gen >
276  INLINE const Priority&
278  const {
279  if (!nb_elements__) { GUM_ERROR(NotFound, "empty priority queue"); }
280 
281  return heap__[0].first;
282  }
283 
284  // returns the number of elements in the priority queue
285  template < typename Val,
286  typename Priority,
287  typename Cmp,
288  typename Alloc,
289  bool Gen >
291  const noexcept {
292  return nb_elements__;
293  }
294 
295  // return the size of the array storing the priority queue
296  template < typename Val,
297  typename Priority,
298  typename Cmp,
299  typename Alloc,
300  bool Gen >
301  INLINE Size
303  const noexcept {
304  return Size(heap__.capacity());
305  }
306 
307  // changes the size of the array storing the priority queue
308  template < typename Val,
309  typename Priority,
310  typename Cmp,
311  typename Alloc,
312  bool Gen >
313  INLINE void
315  Size new_size) {
316  if (new_size < nb_elements__) return;
317 
320  }
321 
322  // removes all the elements from the queue
323  template < typename Val,
324  typename Priority,
325  typename Cmp,
326  typename Alloc,
327  bool Gen >
328  INLINE void
330  nb_elements__ = 0;
331  heap__.clear();
332  indices__.clear();
333  }
334 
335  // removes the element at index elt from the priority queue
336  template < typename Val,
337  typename Priority,
338  typename Cmp,
339  typename Alloc,
340  bool Gen >
342  Size index) {
343  if (index >= nb_elements__) return;
344 
345  // remove the element from the hashtable
347 
348  // put the last element at the "index" location
349  std::pair< Priority, const Val* > last = std::move(heap__[nb_elements__ - 1]);
350  heap__.pop_back();
351  --nb_elements__;
352 
353  if (!nb_elements__ || (index == nb_elements__)) return;
354 
355  // restore the heap property
356  Size i = index;
357 
358  for (Size j = (index << 1) + 1; j < nb_elements__; i = j, j = (j << 1) + 1) {
359  // let j be the max child
360  if ((j + 1 < nb_elements__) && cmp__(heap__[j + 1].first, heap__[j].first))
361  ++j;
362 
363  // if "last" is lower than heap[j], "last" must be stored at index i
364  if (cmp__(last.first, heap__[j].first)) break;
365 
366  // else pull up the jth node
367  heap__[i] = std::move(heap__[j]);
368  indices__[*(heap__[i].second)] = i;
369  }
370 
371  // put "last" back into the heap
372  heap__[i] = std::move(last);
373  indices__[*(heap__[i].second)] = i;
374  }
375 
376  // removes a given element from the priority queue (but does not return it)
377  template < typename Val,
378  typename Priority,
379  typename Cmp,
380  typename Alloc,
381  bool Gen >
383  const Val& val) {
384  try {
386  } catch (NotFound&) {}
387  }
388 
389  // removes the top of the priority queue (but does not return it)
390  template < typename Val,
391  typename Priority,
392  typename Cmp,
393  typename Alloc,
394  bool Gen >
395  INLINE void
397  eraseByPos(0);
398  }
399 
400  // removes the top element from the priority queue and return it
401  template < typename Val,
402  typename Priority,
403  typename Cmp,
404  typename Alloc,
405  bool Gen >
407  if (!nb_elements__) { GUM_ERROR(NotFound, "empty priority queue"); }
408 
409  Val v = *(heap__[0].second);
410  eraseByPos(0);
411 
412  return v;
413  }
414 
415  // returns a hashtable the keys of which are the values stored in the queue
416  template < typename Val,
417  typename Priority,
418  typename Cmp,
419  typename Alloc,
420  bool Gen >
421  INLINE const HashTable< Val, Size >&
423  const noexcept {
424  return reinterpret_cast< const HashTable< Val, Size >& >(indices__);
425  }
426 
427  // inserts a new (a copy) element in the priority queue
428  template < typename Val,
429  typename Priority,
430  typename Cmp,
431  typename Alloc,
432  bool Gen >
433  INLINE Size
435  const Val& val,
436  const Priority& priority) {
437  // create the entry in the indices hashtable (if the element already exists,
438  // indices__.insert will raise a Duplicateelement exception)
440  = indices__.insert(val, 0);
441 
442  try {
444  std::pair< Priority, const Val* >(priority, &new_elt.first));
445  } catch (...) {
447  throw;
448  }
449 
450  std::pair< Priority, const Val* > new_heap_val
452  ++nb_elements__;
453 
454  // restore the heap property
455  Size i = nb_elements__ - 1;
456 
457  for (Size j = (i - 1) >> 1; i && cmp__(new_heap_val.first, heap__[j].first);
458  i = j, j = (j - 1) >> 1) {
459  heap__[i] = std::move(heap__[j]);
460  indices__[*(heap__[i].second)] = i;
461  }
462 
463  // put the new bucket into the heap
465  heap__[i].second = &(new_elt.first);
466  new_elt.second = i;
467 
468  return i;
469  }
470 
471  // inserts by move a new element in the priority queue
472  template < typename Val,
473  typename Priority,
474  typename Cmp,
475  typename Alloc,
476  bool Gen >
477  INLINE Size
479  Val&& val,
480  Priority&& priority) {
481  // create the entry in the indices hashtable (if the element already exists,
482  // indices__.insert will raise a Duplicateelement exception)
484  = indices__.insert(std::move(val), 0);
485 
486  try {
488  std::pair< Priority, const Val* >(std::move(priority), &(new_elt.first)));
489  } catch (...) {
491  throw;
492  }
493 
494  std::pair< Priority, const Val* > new_heap_val
496  ++nb_elements__;
497 
498  // restore the heap property
499  Size i = nb_elements__ - 1;
500 
501  for (Size j = (i - 1) >> 1; i && cmp__(new_heap_val.first, heap__[j].first);
502  i = j, j = (j - 1) >> 1) {
503  heap__[i] = std::move(heap__[j]);
504  indices__[*(heap__[i].second)] = i;
505  }
506 
507  // put the new bucket into the heap
509  heap__[i].second = &(new_elt.first);
510  new_elt.second = i;
511 
512  return i;
513  }
514 
515  // emplace a new element into the priority queue
516  template < typename Val,
517  typename Priority,
518  typename Cmp,
519  typename Alloc,
520  bool Gen >
521  template < typename... Args >
522  INLINE Size
524  Args&&... args) {
526  = std::make_pair< Val, Priority >(std::forward< Args >(args)...);
528  }
529 
530  // indicates whether the priority queue is empty
531  template < typename Val,
532  typename Priority,
533  typename Cmp,
534  typename Alloc,
535  bool Gen >
536  INLINE bool
538  const noexcept {
539  return (nb_elements__ == 0);
540  }
541 
542  // indicates whether the priority queue contains a given value
543  template < typename Val,
544  typename Priority,
545  typename Cmp,
546  typename Alloc,
547  bool Gen >
548  INLINE bool
550  const Val& val) const {
551  return indices__.exists(val);
552  }
553 
554  // returns the element at position "index" in the priority queue
555  template < typename Val,
556  typename Priority,
557  typename Cmp,
558  typename Alloc,
559  bool Gen >
560  INLINE const Val&
562  Size index) const {
563  if (index >= nb_elements__) {
565  "not enough elements in the PriorityQueueImplementation");
566  }
567 
568  return *(heap__[index].second);
569  }
570 
571  // displays the content of the queue
572  template < typename Val,
573  typename Priority,
574  typename Cmp,
575  typename Alloc,
576  bool Gen >
577  std::string
579  const {
580  bool deja = false;
582  stream << "[";
583 
584  for (Size i = 0; i != nb_elements__; ++i, deja = true) {
585  if (deja) stream << " , ";
586 
587  stream << "(" << heap__[i].first << " , " << *(heap__[i].second) << ")";
588  }
589 
590  stream << "]";
591 
592  return stream.str();
593  }
594 
595  // changes the size of the internal structure storing the priority queue
596  template < typename Val,
597  typename Priority,
598  typename Cmp,
599  typename Alloc,
600  bool Gen >
603  // check whether the element the priority of which should be changed exists
604  if (index >= nb_elements__) {
606  "not enough elements in the PriorityQueueImplementation");
607  }
608 
609  // get the element itself
610  const Val* val = heap__[index].second;
611 
612  // restore the heap property
613  Size i = index;
614 
615  // move val upward if needed
616  for (Size j = (i - 1) >> 1; i && cmp__(new_priority, heap__[j].first);
617  i = j, j = (j - 1) >> 1) {
618  heap__[i] = std::move(heap__[j]);
619  indices__[*(heap__[i].second)] = i;
620  }
621 
622  // move val downward if needed
623  for (Size j = (i << 1) + 1; j < nb_elements__; i = j, j = (j << 1) + 1) {
624  // let j be the max child
625  if ((j + 1 < nb_elements__) && cmp__(heap__[j + 1].first, heap__[j].first))
626  ++j;
627 
628  // if "val" is lower than heap[j], "val" must be stored at index i
629  if (cmp__(new_priority, heap__[j].first)) break;
630 
631  // else pull up the jth node
632  heap__[i] = std::move(heap__[j]);
633  indices__[*(heap__[i].second)] = i;
634  }
635 
636  // update the index of val
638  heap__[i].second = val;
639  indices__[*val] = i;
640 
641  return i;
642  }
643 
644  // changes the size of the internal structure storing the priority queue
645  template < typename Val,
646  typename Priority,
647  typename Cmp,
648  typename Alloc,
649  bool Gen >
652  // check whether the element the priority of which should be changed exists
653  if (index >= nb_elements__) {
655  "not enough elements in the PriorityQueueImplementation");
656  }
657 
658  // get the element itself
659  const Val* val = heap__[index].second;
660 
661  // restore the heap property
662  Size i = index;
663 
664  // move val upward if needed
665  for (Size j = (i - 1) >> 1; i && cmp__(new_priority, heap__[j].first);
666  i = j, j = (j - 1) >> 1) {
667  heap__[i] = std::move(heap__[j]);
668  indices__[*(heap__[i].second)] = i;
669  }
670 
671  // move val downward if needed
672  for (Size j = (i << 1) + 1; j < nb_elements__; i = j, j = (j << 1) + 1) {
673  // let j be the max child
674  if ((j + 1 < nb_elements__) && cmp__(heap__[j + 1].first, heap__[j].first))
675  ++j;
676 
677  // if "val" is lower than heap[j], "val" must be stored at index i
678  if (cmp__(new_priority, heap__[j].first)) break;
679 
680  // else pull up the jth node
681  heap__[i] = std::move(heap__[j]);
682  indices__[*(heap__[i].second)] = i;
683  }
684 
685  // update the index of val
687  heap__[i].second = val;
688  indices__[*val] = i;
689 
690  return i;
691  }
692 
693  // modifies the priority of a given element
694  template < typename Val,
695  typename Priority,
696  typename Cmp,
697  typename Alloc,
698  bool Gen >
700  const Val& elt,
701  const Priority& new_priority) {
703  }
704 
705  // modifies the priority of a given element
706  template < typename Val,
707  typename Priority,
708  typename Cmp,
709  typename Alloc,
710  bool Gen >
712  const Val& elt,
715  }
716 
717  // returns the priority of a given element
718  template < typename Val,
719  typename Priority,
720  typename Cmp,
721  typename Alloc,
722  bool Gen >
723  INLINE const Priority&
725  const Val& elt) const {
726  return heap__[indices__[elt]].first;
727  }
728 
729  // returns the priority of a given element
730  template < typename Val,
731  typename Priority,
732  typename Cmp,
733  typename Alloc,
734  bool Gen >
735  INLINE const Priority&
737  Size index) const {
738  if (index > nb_elements__) {
740  "not enough elements in the PriorityQueueImplementation");
741  }
742  return heap__[index].first;
743  }
744 
745  // ===========================================================================
746  // === SCALAR OPTIMIZED IMPLEMENTATION OF PRIORITY QUEUES ===
747  // ===========================================================================
748 
749  // basic constructor
750  template < typename Val, typename Priority, typename Cmp, typename Alloc >
753  indices__(capacity >> 1, true, true),
754  cmp__(compare) {
756 
757  // for debugging purposes
759  }
760 
761  // initializer list constructor
762  template < typename Val, typename Priority, typename Cmp, typename Alloc >
766  indices__(Size(list.size()) / 2, true, true) {
767  // fill the queue
768  heap__.reserve(list.size());
769  for (const auto& elt: list) {
771  }
772 
773  // for debugging purposes
775  }
776 
777  // copy constructor
778  template < typename Val, typename Priority, typename Cmp, typename Alloc >
782  from) :
783  heap__(from.heap__),
785  cmp__(from.cmp__) {
786  // for debugging purposes
788  }
789 
790  // generalized copy constructor
791  template < typename Val, typename Priority, typename Cmp, typename Alloc >
792  template < typename OtherAlloc >
796  from) :
799  // fill the heap structure
800  if (nb_elements__) {
802  for (const auto& elt: from.heap__) {
804  }
805  }
806 
807  // for debugging purposes
809  }
810 
811  // move constructor
812  template < typename Val, typename Priority, typename Cmp, typename Alloc >
819  // for debugging purposes
821  }
822 
823  // destructor
824  template < typename Val, typename Priority, typename Cmp, typename Alloc >
827  // for debugging purposes
829  }
830 
831  // copy operator
832  template < typename Val, typename Priority, typename Cmp, typename Alloc >
836  from) {
837  // avoid self assignment
838  if (this != &from) {
839  // for debugging purposes
841 
842  try {
843  // set the comparison function
844  cmp__ = from.cmp__;
845 
846  // copy the indices and the heap
848  heap__ = from.heap__;
850  } catch (...) {
851  heap__.clear();
852  indices__.clear();
853  nb_elements__ = 0;
854 
855  throw;
856  }
857  }
858 
859  return *this;
860  }
861 
862  // generalized copy operator
863  template < typename Val, typename Priority, typename Cmp, typename Alloc >
864  template < typename OtherAlloc >
868  from) {
869  // for debugging purposes
871 
872  try {
873  // set the comprison function
874  cmp__ = from.cmp__;
875 
876  // copy the indices and the heap
879 
880  heap__.clear();
881  if (nb_elements__) {
883  for (const auto& elt: from.heap__) {
885  }
886  }
887  } catch (...) {
888  heap__.clear();
889  indices__.clear();
890  nb_elements__ = 0;
891 
892  throw;
893  }
894 
895  return *this;
896  }
897 
898  // move operator
899  template < typename Val, typename Priority, typename Cmp, typename Alloc >
903  // avoid self assignment
904  if (this != &from) {
905  // for debugging purposes
907 
909  heap__ = std::move(from.heap__);
910  cmp__ = std::move(from.cmp__);
912  }
913 
914  return *this;
915  }
916 
917  // returns the element at the top of the priority queue
918  template < typename Val, typename Priority, typename Cmp, typename Alloc >
919  INLINE const Val&
920  PriorityQueueImplementation< Val, Priority, Cmp, Alloc, true >::top() const {
921  if (!nb_elements__) { GUM_ERROR(NotFound, "empty priority queue"); }
922 
923  return heap__[0].second;
924  }
925 
926  // returns the priority of the top element
927  template < typename Val, typename Priority, typename Cmp, typename Alloc >
928  INLINE const Priority&
930  const {
931  if (!nb_elements__) { GUM_ERROR(NotFound, "empty priority queue"); }
932 
933  return heap__[0].first;
934  }
935 
936  // returns the number of elements in the priority queue
937  template < typename Val, typename Priority, typename Cmp, typename Alloc >
938  INLINE Size
940  const noexcept {
941  return nb_elements__;
942  }
943 
944  // return the size of the array storing the priority queue
945  template < typename Val, typename Priority, typename Cmp, typename Alloc >
946  INLINE Size
948  const noexcept {
949  return Size(heap__.capacity());
950  }
951 
952  // changes the size of the array storing the priority queue
953  template < typename Val, typename Priority, typename Cmp, typename Alloc >
954  INLINE void
956  Size new_size) {
957  if (new_size < nb_elements__) return;
958 
961  }
962 
963  // removes all the elements from the queue
964  template < typename Val, typename Priority, typename Cmp, typename Alloc >
965  INLINE void
967  nb_elements__ = 0;
968  heap__.clear();
969  indices__.clear();
970  }
971 
972  // removes the element at index elt from the priority queue
973  template < typename Val, typename Priority, typename Cmp, typename Alloc >
975  Size index) {
976  if (index >= nb_elements__) return;
977 
978  // remove the element from the hashtable
980 
981  // put the last element at the "index" location
983  heap__.pop_back();
984  --nb_elements__;
985 
986  if (!nb_elements__ || (index == nb_elements__)) return;
987 
988  // restore the heap property
989  Size i = index;
990 
991  for (Size j = (index << 1) + 1; j < nb_elements__; i = j, j = (j << 1) + 1) {
992  // let j be the max child
993  if ((j + 1 < nb_elements__) && cmp__(heap__[j + 1].first, heap__[j].first))
994  ++j;
995 
996  // if "last" is lower than heap[j], "last" must be stored at index i
997  if (cmp__(last.first, heap__[j].first)) break;
998 
999  // else pull up the jth node
1000  heap__[i] = std::move(heap__[j]);
1001  indices__[heap__[i].second] = i;
1002  }
1003 
1004  // put "last" back into the heap
1005  heap__[i] = std::move(last);
1006  indices__[heap__[i].second] = i;
1007  }
1008 
1009  // removes a given element from the priority queue (but does not return it)
1010  template < typename Val, typename Priority, typename Cmp, typename Alloc >
1011  INLINE void
1013  Val val) {
1014  try {
1016  } catch (NotFound&) {}
1017  }
1018 
1019  // removes the top of the priority queue (but does not return it)
1020  template < typename Val, typename Priority, typename Cmp, typename Alloc >
1021  INLINE void
1023  eraseByPos(0);
1024  }
1025 
1026  // removes the top element from the priority queue and return it
1027  template < typename Val, typename Priority, typename Cmp, typename Alloc >
1028  INLINE Val
1030  if (!nb_elements__) { GUM_ERROR(NotFound, "empty priority queue"); }
1031 
1032  Val v = heap__[0].second;
1033  eraseByPos(0);
1034 
1035  return v;
1036  }
1037 
1038  // returns a hashtable the keys of which are the values stored in the queue
1039  template < typename Val, typename Priority, typename Cmp, typename Alloc >
1040  INLINE const HashTable< Val, Size >&
1042  const noexcept {
1043  return reinterpret_cast< const HashTable< Val, Size >& >(indices__);
1044  }
1045 
1046  // inserts a new (a copy) element in the priority queue
1047  template < typename Val, typename Priority, typename Cmp, typename Alloc >
1048  INLINE Size
1050  Val val,
1051  const Priority& priority) {
1052  // create the entry in the indices hashtable (if the element already exists,
1053  // indices__.insert will raise a Duplicateelement exception)
1055  = indices__.insert(val, 0);
1056 
1057  try {
1059  } catch (...) {
1060  indices__.erase(val);
1061  throw;
1062  }
1063 
1065  ++nb_elements__;
1066 
1067  // restore the heap property
1068  Size i = nb_elements__ - 1;
1069 
1070  for (Size j = (i - 1) >> 1; i && cmp__(new_heap_val.first, heap__[j].first);
1071  i = j, j = (j - 1) >> 1) {
1072  heap__[i] = std::move(heap__[j]);
1073  indices__[heap__[i].second] = i;
1074  }
1075 
1076  // put the new bucket into the heap
1078  heap__[i].second = val;
1079  new_elt.second = i;
1080 
1081  return i;
1082  }
1083 
1084  // inserts by move a new element in the priority queue
1085  template < typename Val, typename Priority, typename Cmp, typename Alloc >
1086  INLINE Size
1088  Val val,
1089  Priority&& priority) {
1090  // create the entry in the indices hashtable (if the element already exists,
1091  // indices__.insert will raise a Duplicateelement exception)
1093  = indices__.insert(val, 0);
1094 
1095  try {
1097  } catch (...) {
1098  indices__.erase(val);
1099  throw;
1100  }
1101 
1103  ++nb_elements__;
1104 
1105  // restore the heap property
1106  Size i = nb_elements__ - 1;
1107 
1108  for (Size j = (i - 1) >> 1; i && cmp__(new_heap_val.first, heap__[j].first);
1109  i = j, j = (j - 1) >> 1) {
1110  heap__[i] = std::move(heap__[j]);
1111  indices__[heap__[i].second] = i;
1112  }
1113 
1114  // put the new bucket into the heap
1116  heap__[i].second = val;
1117  new_elt.second = i;
1118 
1119  return i;
1120  }
1121 
1122  // emplace a new element into the priority queue
1123  template < typename Val, typename Priority, typename Cmp, typename Alloc >
1124  template < typename... Args >
1125  INLINE Size
1127  Args&&... args) {
1128  std::pair< Val, Priority > new_elt
1129  = std::make_pair< Val, Priority >(std::forward< Args >(args)...);
1130  return insert(new_elt.first, std::move(new_elt.second));
1131  }
1132 
1133  // indicates whether the priority queue is empty
1134  template < typename Val, typename Priority, typename Cmp, typename Alloc >
1135  INLINE bool
1137  const noexcept {
1138  return (nb_elements__ == 0);
1139  }
1140 
1141  // indicates whether the priority queue contains a given value
1142  template < typename Val, typename Priority, typename Cmp, typename Alloc >
1143  INLINE bool
1145  Val val) const {
1146  return indices__.exists(val);
1147  }
1148 
1149  // returns the element at position "index" in the priority queue
1150  template < typename Val, typename Priority, typename Cmp, typename Alloc >
1151  INLINE const Val&
1153  Size index) const {
1154  if (index >= nb_elements__) {
1156  "not enough elements in the PriorityQueueImplementation");
1157  }
1158 
1159  return heap__[index].second;
1160  }
1161 
1162  // displays the content of the queue
1163  template < typename Val, typename Priority, typename Cmp, typename Alloc >
1164  std::string
1166  const {
1167  bool deja = false;
1169  stream << "[";
1170 
1171  for (Size i = 0; i != nb_elements__; ++i, deja = true) {
1172  if (deja) stream << " , ";
1173 
1174  stream << "(" << heap__[i].first << " , " << heap__[i].second << ")";
1175  }
1176 
1177  stream << "]";
1178 
1179  return stream.str();
1180  }
1181 
1182  // changes the size of the internal structure storing the priority queue
1183  template < typename Val, typename Priority, typename Cmp, typename Alloc >
1186  // check whether the element the priority of which should be changed exists
1187  if (index >= nb_elements__) {
1189  "not enough elements in the PriorityQueueImplementation");
1190  }
1191 
1192  // get the element itself
1193  Val val = heap__[index].second;
1194 
1195  // restore the heap property
1196  Size i = index;
1197 
1198  // move val upward if needed
1199  for (Size j = (i - 1) >> 1; i && cmp__(new_priority, heap__[j].first);
1200  i = j, j = (j - 1) >> 1) {
1201  heap__[i] = std::move(heap__[j]);
1202  indices__[heap__[i].second] = i;
1203  }
1204 
1205  // move val downward if needed
1206  for (Size j = (i << 1) + 1; j < nb_elements__; i = j, j = (j << 1) + 1) {
1207  // let j be the max child
1208  if ((j + 1 < nb_elements__) && cmp__(heap__[j + 1].first, heap__[j].first))
1209  ++j;
1210 
1211  // if "val" is lower than heap[j], "val" must be stored at index i
1212  if (cmp__(new_priority, heap__[j].first)) break;
1213 
1214  // else pull up the jth node
1215  heap__[i] = std::move(heap__[j]);
1216  indices__[heap__[i].second] = i;
1217  }
1218 
1219  // update the index of val
1221  heap__[i].second = val;
1222  indices__[val] = i;
1223 
1224  return i;
1225  }
1226 
1227  // changes the size of the internal structure storing the priority queue
1228  template < typename Val, typename Priority, typename Cmp, typename Alloc >
1231  // check whether the element the priority of which should be changed exists
1232  if (index >= nb_elements__) {
1234  "not enough elements in the PriorityQueueImplementation");
1235  }
1236 
1237  // get the element itself
1238  Val val = heap__[index].second;
1239 
1240  // restore the heap property
1241  Size i = index;
1242 
1243  // move val upward if needed
1244  for (Size j = (i - 1) >> 1; i && cmp__(new_priority, heap__[j].first);
1245  i = j, j = (j - 1) >> 1) {
1246  heap__[i] = std::move(heap__[j]);
1247  indices__[heap__[i].second] = i;
1248  }
1249 
1250  // move val downward if needed
1251  for (Size j = (i << 1) + 1; j < nb_elements__; i = j, j = (j << 1) + 1) {
1252  // let j be the max child
1253  if ((j + 1 < nb_elements__) && cmp__(heap__[j + 1].first, heap__[j].first))
1254  ++j;
1255 
1256  // if "val" is lower than heap[j], "val" must be stored at index i
1257  if (cmp__(new_priority, heap__[j].first)) break;
1258 
1259  // else pull up the jth node
1260  heap__[i] = std::move(heap__[j]);
1261  indices__[heap__[i].second] = i;
1262  }
1263 
1264  // update the index of val
1266  heap__[i].second = val;
1267  indices__[val] = i;
1268 
1269  return i;
1270  }
1271 
1272  // modifies the priority of a given element
1273  template < typename Val, typename Priority, typename Cmp, typename Alloc >
1275  Val elt,
1276  const Priority& new_priority) {
1278  }
1279 
1280  // modifies the priority of a given element
1281  template < typename Val, typename Priority, typename Cmp, typename Alloc >
1283  Val elt,
1284  Priority&& new_priority) {
1286  }
1287 
1288  // returns the priority of a given element
1289  template < typename Val, typename Priority, typename Cmp, typename Alloc >
1290  INLINE const Priority&
1292  Val elt) const {
1293  return heap__[indices__[elt]].first;
1294  }
1295 
1296  // returns the priority of a given element
1297  template < typename Val, typename Priority, typename Cmp, typename Alloc >
1298  INLINE const Priority&
1300  Size index) const {
1301  if (index > nb_elements__) {
1303  "not enough elements in the PriorityQueueImplementation");
1304  }
1305  return heap__[index].first;
1306  }
1307 
1308  // ===========================================================================
1309  // === PRIORITY QUEUES ===
1310  // ===========================================================================
1311 
1312  // basic constructor
1313  template < typename Val, typename Priority, typename Cmp, typename Alloc >
1315  Size capacity) :
1317  // for debugging purposes
1319  }
1320 
1321  // initializer list constructor
1322  template < typename Val, typename Priority, typename Cmp, typename Alloc >
1326  // for debugging purposes
1328  }
1329 
1330  // copy constructor
1331  template < typename Val, typename Priority, typename Cmp, typename Alloc >
1333  const PriorityQueue< Val, Priority, Cmp, Alloc >& from) :
1335  // for debugging purposes
1337  }
1338 
1339  // generalized copy constructor
1340  template < typename Val, typename Priority, typename Cmp, typename Alloc >
1341  template < typename OtherAlloc >
1343  const PriorityQueue< Val, Priority, Cmp, OtherAlloc >& from) :
1345  // for debugging purposes
1347  }
1348 
1349  // move constructor
1350  template < typename Val, typename Priority, typename Cmp, typename Alloc >
1352  PriorityQueue< Val, Priority, Cmp, Alloc >&& from) :
1354  // for debugging purposes
1356  }
1357 
1358  // destructor
1359  template < typename Val, typename Priority, typename Cmp, typename Alloc >
1361  // for debugging purposes
1363  }
1364 
1365  // copy operator
1366  template < typename Val, typename Priority, typename Cmp, typename Alloc >
1369  const PriorityQueue< Val, Priority, Cmp, Alloc >& from) {
1371  return *this;
1372  }
1373 
1374  // generalized copy operator
1375  template < typename Val, typename Priority, typename Cmp, typename Alloc >
1376  template < typename OtherAlloc >
1379  const PriorityQueue< Val, Priority, Cmp, OtherAlloc >& from) {
1381  return *this;
1382  }
1383 
1384  // move operator
1385  template < typename Val, typename Priority, typename Cmp, typename Alloc >
1388  PriorityQueue< Val, Priority, Cmp, Alloc >&& from) {
1390  return *this;
1391  }
1392 
1393  // A \c << operator for priority queues
1394  template < typename Val, typename Priority, typename Cmp, typename Alloc >
1395  INLINE std::ostream&
1397  const PriorityQueue< Val, Priority, Cmp, Alloc >& queue) {
1398  stream << queue.toString();
1399  return stream;
1400  }
1401 
1402 } /* namespace gum */
INLINE void emplace(Args &&... args)
Definition: set_tpl.h:669