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
>::
44
PriorityQueueImplementation
(
Cmp
compare
,
Size
capacity
) :
45
indices__
(
capacity
>> 1,
true
,
true
),
46
cmp__
(
compare
) {
47
heap__
.
reserve
(
capacity
);
48
49
// for debugging purposes
50
GUM_CONSTRUCTOR
(
PriorityQueueImplementation
);
51
}
52
53
// initializer list constructor
54
template
<
typename
Val
,
55
typename
Priority
,
56
typename
Cmp
,
57
typename
Alloc
,
58
bool
Gen
>
59
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
60
PriorityQueueImplementation
(
61
std
::
initializer_list
<
std
::
pair
<
Val
,
Priority
> >
list
) :
62
indices__
(
Size
(
list
.
size
()) / 2,
true
,
true
) {
63
// fill the queue
64
heap__
.
reserve
(
list
.
size
());
65
for
(
const
auto
&
elt
:
list
) {
66
insert
(
elt
.
first
,
elt
.
second
);
67
}
68
69
// for debugging purposes
70
GUM_CONSTRUCTOR
(
PriorityQueueImplementation
);
71
}
72
73
// copy constructor
74
template
<
typename
Val
,
75
typename
Priority
,
76
typename
Cmp
,
77
typename
Alloc
,
78
bool
Gen
>
79
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
80
PriorityQueueImplementation
(
81
const
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>&
82
from
) :
83
heap__
(
from
.
heap__
),
84
indices__
(
from
.
indices__
),
nb_elements__
(
from
.
nb_elements__
),
85
cmp__
(
from
.
cmp__
) {
86
// fill the heap structure
87
for
(
const
auto
&
elt
:
indices__
) {
88
heap__
[
elt
.
second
].
second
= &(
elt
.
first
);
89
}
90
91
// for debugging purposes
92
GUM_CONS_CPY
(
PriorityQueueImplementation
);
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
>
102
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
103
PriorityQueueImplementation
(
104
const
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
OtherAlloc
,
Gen
>&
105
from
) :
106
indices__
(
from
.
indices__
),
107
nb_elements__
(
from
.
nb_elements__
),
cmp__
(
from
.
cmp__
) {
108
// fill the heap structure
109
if
(
nb_elements__
) {
110
heap__
.
reserve
(
from
.
heap__
.
size
());
111
for
(
const
auto
&
elt
:
from
.
heap__
) {
112
heap__
.
push_back
(
elt
);
113
}
114
for
(
const
auto
&
elt
:
indices__
) {
115
heap__
[
elt
.
second
].
second
= &(
elt
.
first
);
116
}
117
}
118
119
// for debugging purposes
120
GUM_CONS_CPY
(
PriorityQueueImplementation
);
121
}
122
123
// move constructor
124
template
<
typename
Val
,
125
typename
Priority
,
126
typename
Cmp
,
127
typename
Alloc
,
128
bool
Gen
>
129
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
130
PriorityQueueImplementation
(
131
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>&&
from
) :
132
heap__
(
std
::
move
(
from
.
heap__
)),
133
indices__
(
std
::
move
(
from
.
indices__
)),
134
nb_elements__
(
std
::
move
(
from
.
nb_elements__
)),
cmp__
(
std
::
move
(
from
.
cmp__
)) {
135
// for debugging purposes
136
GUM_CONS_MOV
(
PriorityQueueImplementation
);
137
}
138
139
// destructor
140
template
<
typename
Val
,
141
typename
Priority
,
142
typename
Cmp
,
143
typename
Alloc
,
144
bool
Gen
>
145
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
146
~
PriorityQueueImplementation
() {
147
// for debugging purposes
148
GUM_DESTRUCTOR
(
PriorityQueueImplementation
);
149
}
150
151
// copy operator
152
template
<
typename
Val
,
153
typename
Priority
,
154
typename
Cmp
,
155
typename
Alloc
,
156
bool
Gen
>
157
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>&
158
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
operator
=(
159
const
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>&
160
from
) {
161
// avoid self assignment
162
if
(
this
!= &
from
) {
163
// for debugging purposes
164
GUM_OP_CPY
(
PriorityQueueImplementation
);
165
166
try
{
167
// set the comparison function
168
cmp__
=
from
.
cmp__
;
169
170
// copy the indices and the heap
171
indices__
=
from
.
indices__
;
172
heap__
=
from
.
heap__
;
173
nb_elements__
=
from
.
nb_elements__
;
174
175
// restore the link between indices__ and heap__
176
for
(
const
auto
&
elt
:
indices__
) {
177
heap__
[
elt
.
second
].
second
= &(
elt
.
first
);
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
>
198
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>&
199
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
operator
=(
200
const
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
OtherAlloc
,
Gen
>&
201
from
) {
202
// for debugging purposes
203
GUM_OP_CPY
(
PriorityQueueImplementation
);
204
205
try
{
206
// set the comprison function
207
cmp__
=
from
.
cmp__
;
208
209
// copy the indices and the heap
210
indices__
=
from
.
indices__
;
211
nb_elements__
=
from
.
nb_elements__
;
212
213
heap__
.
clear
();
214
if
(
nb_elements__
) {
215
heap__
.
reserve
(
from
.
heap__
.
size
());
216
for
(
const
auto
&
elt
:
from
.
heap__
) {
217
heap__
.
push_back
(
elt
);
218
}
219
for
(
const
auto
&
elt
:
indices__
) {
220
heap__
[
elt
.
second
].
second
= &(
elt
.
first
);
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
>
240
INLINE
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>&
241
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
operator
=(
242
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>&&
from
) {
243
// avoid self assignment
244
if
(
this
!= &
from
) {
245
// for debugging purposes
246
GUM_OP_MOV
(
PriorityQueueImplementation
);
247
248
indices__
=
std
::
move
(
from
.
indices__
);
249
heap__
=
std
::
move
(
from
.
heap__
);
250
cmp__
=
std
::
move
(
from
.
cmp__
);
251
nb_elements__
=
std
::
move
(
from
.
nb_elements__
);
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
&
264
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
top
()
const
{
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
&
277
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
topPriority
()
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
>
290
INLINE
Size
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
size
()
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
302
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
capacity
()
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
314
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
resize
(
315
Size
new_size
) {
316
if
(
new_size
<
nb_elements__
)
return
;
317
318
heap__
.
reserve
(
new_size
);
319
indices__
.
resize
(
new_size
/ 2);
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
329
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
clear
() {
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
>
341
void
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
eraseByPos
(
342
Size
index
) {
343
if
(
index
>=
nb_elements__
)
return
;
344
345
// remove the element from the hashtable
346
indices__
.
erase
(*(
heap__
[
index
].
second
));
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
>
382
INLINE
void
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
erase
(
383
const
Val
&
val
) {
384
try
{
385
eraseByPos
(
indices__
[
val
]);
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
396
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
eraseTop
() {
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
>
406
INLINE
Val
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
pop
() {
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
>&
422
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
allValues
()
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
434
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
insert
(
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)
439
typename
HashTable
<
Val
,
Size
,
IndexAllocator
>::
value_type
&
new_elt
440
=
indices__
.
insert
(
val
, 0);
441
442
try
{
443
heap__
.
push_back
(
444
std
::
pair
<
Priority
,
const
Val
* >(
priority
, &
new_elt
.
first
));
445
}
catch
(...) {
446
indices__
.
erase
(
val
);
447
throw
;
448
}
449
450
std
::
pair
<
Priority
,
const
Val
* >
new_heap_val
451
=
std
::
move
(
heap__
[
nb_elements__
]);
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
464
heap__
[
i
].
first
=
std
::
move
(
new_heap_val
.
first
);
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
478
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
insert
(
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)
483
typename
HashTable
<
Val
,
Size
,
IndexAllocator
>::
value_type
&
new_elt
484
=
indices__
.
insert
(
std
::
move
(
val
), 0);
485
486
try
{
487
heap__
.
push_back
(
488
std
::
pair
<
Priority
,
const
Val
* >(
std
::
move
(
priority
), &(
new_elt
.
first
)));
489
}
catch
(...) {
490
indices__
.
erase
(
new_elt
.
first
);
491
throw
;
492
}
493
494
std
::
pair
<
Priority
,
const
Val
* >
new_heap_val
495
=
std
::
move
(
heap__
[
nb_elements__
]);
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
508
heap__
[
i
].
first
=
std
::
move
(
new_heap_val
.
first
);
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
523
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
emplace
(
524
Args
&&...
args
) {
525
std
::
pair
<
Val
,
Priority
>
new_elt
526
=
std
::
make_pair
<
Val
,
Priority
>(
std
::
forward
<
Args
>(
args
)...);
527
return
insert
(
std
::
move
(
new_elt
.
first
),
std
::
move
(
new_elt
.
second
));
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
537
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
empty
()
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
549
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
contains
(
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
&
561
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
operator
[](
562
Size
index
)
const
{
563
if
(
index
>=
nb_elements__
) {
564
GUM_ERROR
(
NotFound
,
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
578
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
toString
()
579
const
{
580
bool
deja
=
false
;
581
std
::
stringstream
stream
;
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
>
601
Size
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
602
setPriorityByPos
(
Size
index
,
const
Priority
&
new_priority
) {
603
// check whether the element the priority of which should be changed exists
604
if
(
index
>=
nb_elements__
) {
605
GUM_ERROR
(
NotFound
,
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
637
heap__
[
i
].
first
=
new_priority
;
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
>
650
Size
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
651
setPriorityByPos
(
Size
index
,
Priority
&&
new_priority
) {
652
// check whether the element the priority of which should be changed exists
653
if
(
index
>=
nb_elements__
) {
654
GUM_ERROR
(
NotFound
,
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
686
heap__
[
i
].
first
=
std
::
move
(
new_priority
);
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
>
699
void
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
setPriority
(
700
const
Val
&
elt
,
701
const
Priority
&
new_priority
) {
702
setPriorityByPos
(
indices__
[
elt
],
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
>
711
void
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
setPriority
(
712
const
Val
&
elt
,
713
Priority
&&
new_priority
) {
714
setPriorityByPos
(
indices__
[
elt
],
std
::
move
(
new_priority
));
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
&
724
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
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
&
736
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
priorityByPos
(
737
Size
index
)
const
{
738
if
(
index
>
nb_elements__
) {
739
GUM_ERROR
(
NotFound
,
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
>
751
INLINE
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
752
PriorityQueueImplementation
(
Cmp
compare
,
Size
capacity
) :
753
indices__
(
capacity
>> 1,
true
,
true
),
754
cmp__
(
compare
) {
755
heap__
.
reserve
(
capacity
);
756
757
// for debugging purposes
758
GUM_CONSTRUCTOR
(
PriorityQueueImplementation
);
759
}
760
761
// initializer list constructor
762
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
763
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
764
PriorityQueueImplementation
(
765
std
::
initializer_list
<
std
::
pair
<
Val
,
Priority
> >
list
) :
766
indices__
(
Size
(
list
.
size
()) / 2,
true
,
true
) {
767
// fill the queue
768
heap__
.
reserve
(
list
.
size
());
769
for
(
const
auto
&
elt
:
list
) {
770
insert
(
elt
.
first
,
elt
.
second
);
771
}
772
773
// for debugging purposes
774
GUM_CONSTRUCTOR
(
PriorityQueueImplementation
);
775
}
776
777
// copy constructor
778
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
779
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
780
PriorityQueueImplementation
(
781
const
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>&
782
from
) :
783
heap__
(
from
.
heap__
),
784
indices__
(
from
.
indices__
),
nb_elements__
(
from
.
nb_elements__
),
785
cmp__
(
from
.
cmp__
) {
786
// for debugging purposes
787
GUM_CONS_CPY
(
PriorityQueueImplementation
);
788
}
789
790
// generalized copy constructor
791
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
792
template
<
typename
OtherAlloc
>
793
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
794
PriorityQueueImplementation
(
795
const
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
OtherAlloc
,
true
>&
796
from
) :
797
indices__
(
from
.
indices__
),
798
nb_elements__
(
from
.
nb_elements__
),
cmp__
(
from
.
cmp__
) {
799
// fill the heap structure
800
if
(
nb_elements__
) {
801
heap__
.
reserve
(
from
.
heap__
.
size
());
802
for
(
const
auto
&
elt
:
from
.
heap__
) {
803
heap__
.
push_back
(
elt
);
804
}
805
}
806
807
// for debugging purposes
808
GUM_CONS_CPY
(
PriorityQueueImplementation
);
809
}
810
811
// move constructor
812
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
813
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
814
PriorityQueueImplementation
(
815
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>&&
from
) :
816
heap__
(
std
::
move
(
from
.
heap__
)),
817
indices__
(
std
::
move
(
from
.
indices__
)),
818
nb_elements__
(
std
::
move
(
from
.
nb_elements__
)),
cmp__
(
std
::
move
(
from
.
cmp__
)) {
819
// for debugging purposes
820
GUM_CONS_MOV
(
PriorityQueueImplementation
);
821
}
822
823
// destructor
824
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
825
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
826
~
PriorityQueueImplementation
() {
827
// for debugging purposes
828
GUM_DESTRUCTOR
(
PriorityQueueImplementation
);
829
}
830
831
// copy operator
832
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
833
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>&
834
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
operator
=(
835
const
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>&
836
from
) {
837
// avoid self assignment
838
if
(
this
!= &
from
) {
839
// for debugging purposes
840
GUM_OP_CPY
(
PriorityQueueImplementation
);
841
842
try
{
843
// set the comparison function
844
cmp__
=
from
.
cmp__
;
845
846
// copy the indices and the heap
847
indices__
=
from
.
indices__
;
848
heap__
=
from
.
heap__
;
849
nb_elements__
=
from
.
nb_elements__
;
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
>
865
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>&
866
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
operator
=(
867
const
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
OtherAlloc
,
true
>&
868
from
) {
869
// for debugging purposes
870
GUM_OP_CPY
(
PriorityQueueImplementation
);
871
872
try
{
873
// set the comprison function
874
cmp__
=
from
.
cmp__
;
875
876
// copy the indices and the heap
877
indices__
=
from
.
indices__
;
878
nb_elements__
=
from
.
nb_elements__
;
879
880
heap__
.
clear
();
881
if
(
nb_elements__
) {
882
heap__
.
reserve
(
from
.
heap__
.
size
());
883
for
(
const
auto
&
elt
:
from
.
heap__
) {
884
heap__
.
push_back
(
elt
);
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
>
900
INLINE
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>&
901
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
operator
=(
902
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>&&
from
) {
903
// avoid self assignment
904
if
(
this
!= &
from
) {
905
// for debugging purposes
906
GUM_OP_MOV
(
PriorityQueueImplementation
);
907
908
indices__
=
std
::
move
(
from
.
indices__
);
909
heap__
=
std
::
move
(
from
.
heap__
);
910
cmp__
=
std
::
move
(
from
.
cmp__
);
911
nb_elements__
=
std
::
move
(
from
.
nb_elements__
);
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
&
929
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
topPriority
()
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
939
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
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
947
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
capacity
()
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
955
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
resize
(
956
Size
new_size
) {
957
if
(
new_size
<
nb_elements__
)
return
;
958
959
heap__
.
reserve
(
new_size
);
960
indices__
.
resize
(
new_size
/ 2);
961
}
962
963
// removes all the elements from the queue
964
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
965
INLINE
void
966
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
clear
() {
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
>
974
void
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
eraseByPos
(
975
Size
index
) {
976
if
(
index
>=
nb_elements__
)
return
;
977
978
// remove the element from the hashtable
979
indices__
.
erase
(
heap__
[
index
].
second
);
980
981
// put the last element at the "index" location
982
std
::
pair
<
Priority
,
Val
>
last
=
std
::
move
(
heap__
[
nb_elements__
- 1]);
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
1012
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
erase
(
1013
Val
val
) {
1014
try
{
1015
eraseByPos
(
indices__
[
val
]);
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
1022
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
eraseTop
() {
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
1029
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
pop
() {
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
>&
1041
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
allValues
()
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
1049
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
insert
(
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)
1054
typename
HashTable
<
Val
,
Size
,
IndexAllocator
>::
value_type
&
new_elt
1055
=
indices__
.
insert
(
val
, 0);
1056
1057
try
{
1058
heap__
.
push_back
(
std
::
pair
<
Priority
,
Val
>(
priority
,
val
));
1059
}
catch
(...) {
1060
indices__
.
erase
(
val
);
1061
throw
;
1062
}
1063
1064
std
::
pair
<
Priority
,
Val
>
new_heap_val
=
std
::
move
(
heap__
[
nb_elements__
]);
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
1077
heap__
[
i
].
first
=
std
::
move
(
new_heap_val
.
first
);
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
1087
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
insert
(
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)
1092
typename
HashTable
<
Val
,
Size
,
IndexAllocator
>::
value_type
&
new_elt
1093
=
indices__
.
insert
(
val
, 0);
1094
1095
try
{
1096
heap__
.
push_back
(
std
::
pair
<
Priority
,
Val
>(
std
::
move
(
priority
),
val
));
1097
}
catch
(...) {
1098
indices__
.
erase
(
val
);
1099
throw
;
1100
}
1101
1102
std
::
pair
<
Priority
,
Val
>
new_heap_val
=
std
::
move
(
heap__
[
nb_elements__
]);
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
1115
heap__
[
i
].
first
=
std
::
move
(
new_heap_val
.
first
);
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
1126
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
emplace
(
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
1136
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
empty
()
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
1144
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
contains
(
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
&
1152
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
operator
[](
1153
Size
index
)
const
{
1154
if
(
index
>=
nb_elements__
) {
1155
GUM_ERROR
(
NotFound
,
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
1165
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
toString
()
1166
const
{
1167
bool
deja
=
false
;
1168
std
::
stringstream
stream
;
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
>
1184
Size
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
1185
setPriorityByPos
(
Size
index
,
const
Priority
&
new_priority
) {
1186
// check whether the element the priority of which should be changed exists
1187
if
(
index
>=
nb_elements__
) {
1188
GUM_ERROR
(
NotFound
,
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
1220
heap__
[
i
].
first
=
new_priority
;
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
>
1229
Size
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
1230
setPriorityByPos
(
Size
index
,
Priority
&&
new_priority
) {
1231
// check whether the element the priority of which should be changed exists
1232
if
(
index
>=
nb_elements__
) {
1233
GUM_ERROR
(
NotFound
,
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
1265
heap__
[
i
].
first
=
std
::
move
(
new_priority
);
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
>
1274
void
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
setPriority
(
1275
Val
elt
,
1276
const
Priority
&
new_priority
) {
1277
setPriorityByPos
(
indices__
[
elt
],
new_priority
);
1278
}
1279
1280
// modifies the priority of a given element
1281
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
1282
void
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
setPriority
(
1283
Val
elt
,
1284
Priority
&&
new_priority
) {
1285
setPriorityByPos
(
indices__
[
elt
],
std
::
move
(
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
&
1291
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
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
&
1299
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
priorityByPos
(
1300
Size
index
)
const
{
1301
if
(
index
>
nb_elements__
) {
1302
GUM_ERROR
(
NotFound
,
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
>
1314
INLINE
PriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
PriorityQueue
(
Cmp
cmp
,
1315
Size
capacity
) :
1316
PriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
Implementation
(
cmp
,
capacity
) {
1317
// for debugging purposes
1318
GUM_CONSTRUCTOR
(
PriorityQueue
);
1319
}
1320
1321
// initializer list constructor
1322
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
1323
INLINE
PriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
PriorityQueue
(
1324
std
::
initializer_list
<
std
::
pair
<
Val
,
Priority
> >
list
) :
1325
PriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
Implementation
{
list
} {
1326
// for debugging purposes
1327
GUM_CONSTRUCTOR
(
PriorityQueue
);
1328
}
1329
1330
// copy constructor
1331
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
1332
INLINE
PriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
PriorityQueue
(
1333
const
PriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>&
from
) :
1334
PriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
Implementation
(
from
) {
1335
// for debugging purposes
1336
GUM_CONS_CPY
(
PriorityQueue
);
1337
}
1338
1339
// generalized copy constructor
1340
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
1341
template
<
typename
OtherAlloc
>
1342
INLINE
PriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
PriorityQueue
(
1343
const
PriorityQueue
<
Val
,
Priority
,
Cmp
,
OtherAlloc
>&
from
) :
1344
PriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
Implementation
(
from
) {
1345
// for debugging purposes
1346
GUM_CONS_CPY
(
PriorityQueue
);
1347
}
1348
1349
// move constructor
1350
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
1351
INLINE
PriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
PriorityQueue
(
1352
PriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>&&
from
) :
1353
PriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
Implementation
(
std
::
move
(
from
)) {
1354
// for debugging purposes
1355
GUM_CONS_MOV
(
PriorityQueue
);
1356
}
1357
1358
// destructor
1359
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
1360
INLINE
PriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::~
PriorityQueue
() {
1361
// for debugging purposes
1362
GUM_DESTRUCTOR
(
PriorityQueue
);
1363
}
1364
1365
// copy operator
1366
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
1367
INLINE
PriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>&
1368
PriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
operator
=(
1369
const
PriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>&
from
) {
1370
Implementation
::
operator
=(
from
);
1371
return
*
this
;
1372
}
1373
1374
// generalized copy operator
1375
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
1376
template
<
typename
OtherAlloc
>
1377
INLINE
PriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>&
1378
PriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
operator
=(
1379
const
PriorityQueue
<
Val
,
Priority
,
Cmp
,
OtherAlloc
>&
from
) {
1380
Implementation
::
operator
=(
from
);
1381
return
*
this
;
1382
}
1383
1384
// move operator
1385
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
1386
INLINE
PriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>&
1387
PriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
operator
=(
1388
PriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>&&
from
) {
1389
Implementation
::
operator
=(
std
::
move
(
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
&
1396
operator
<<(
std
::
ostream
&
stream
,
1397
const
PriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>&
queue
) {
1398
stream
<<
queue
.
toString
();
1399
return
stream
;
1400
}
1401
1402
}
/* namespace gum */
gum::Set::emplace
INLINE void emplace(Args &&... args)
Definition:
set_tpl.h:669