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
) {
44
_heap_
.
reserve
(
capacity
);
45
46
GUM_CONSTRUCTOR
(
PriorityQueueImplementation
);
47
}
48
49
// initializer list constructor
50
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
,
bool
Gen
>
51
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
PriorityQueueImplementation
(
52
std
::
initializer_list
<
std
::
pair
<
Val
,
Priority
> >
list
) :
53
_indices_
(
Size
(
list
.
size
()) / 2,
true
,
true
) {
54
// fill the queue
55
_heap_
.
reserve
(
list
.
size
());
56
for
(
const
auto
&
elt
:
list
) {
57
insert
(
elt
.
first
,
elt
.
second
);
58
}
59
60
GUM_CONSTRUCTOR
(
PriorityQueueImplementation
);
61
}
62
63
// copy constructor
64
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
,
bool
Gen
>
65
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
PriorityQueueImplementation
(
66
const
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>&
from
) :
67
_heap_
(
from
.
_heap_
),
68
_indices_
(
from
.
_indices_
),
_nb_elements_
(
from
.
_nb_elements_
),
_cmp_
(
from
.
_cmp_
) {
69
// fill the heap structure
70
for
(
const
auto
&
elt
:
_indices_
) {
71
_heap_
[
elt
.
second
].
second
= &(
elt
.
first
);
72
}
73
74
GUM_CONS_CPY
(
PriorityQueueImplementation
);
75
}
76
77
// generalized copy constructor
78
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
,
bool
Gen
>
79
template
<
typename
OtherAlloc
>
80
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
PriorityQueueImplementation
(
81
const
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
OtherAlloc
,
Gen
>&
from
) :
82
_indices_
(
from
.
_indices_
),
83
_nb_elements_
(
from
.
_nb_elements_
),
_cmp_
(
from
.
_cmp_
) {
84
// fill the heap structure
85
if
(
_nb_elements_
) {
86
_heap_
.
reserve
(
from
.
_heap_
.
size
());
87
for
(
const
auto
&
elt
:
from
.
_heap_
) {
88
_heap_
.
push_back
(
elt
);
89
}
90
for
(
const
auto
&
elt
:
_indices_
) {
91
_heap_
[
elt
.
second
].
second
= &(
elt
.
first
);
92
}
93
}
94
95
GUM_CONS_CPY
(
PriorityQueueImplementation
);
96
}
97
98
// move constructor
99
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
,
bool
Gen
>
100
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
PriorityQueueImplementation
(
101
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>&&
from
) :
102
_heap_
(
std
::
move
(
from
.
_heap_
)),
103
_indices_
(
std
::
move
(
from
.
_indices_
)),
_nb_elements_
(
std
::
move
(
from
.
_nb_elements_
)),
104
_cmp_
(
std
::
move
(
from
.
_cmp_
)) {
105
GUM_CONS_MOV
(
PriorityQueueImplementation
)
106
}
107
108
// destructor
109
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
,
bool
Gen
>
110
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::~
PriorityQueueImplementation
() {
111
GUM_DESTRUCTOR
(
PriorityQueueImplementation
);
112
}
113
114
// copy operator
115
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
,
bool
Gen
>
116
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>&
117
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
operator
=(
118
const
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>&
from
) {
119
// avoid self assignment
120
if
(
this
!= &
from
) {
121
GUM_OP_CPY
(
PriorityQueueImplementation
)
122
123
try
{
124
// set the comparison function
125
_cmp_
=
from
.
_cmp_
;
126
127
// copy the indices and the heap
128
_indices_
=
from
.
_indices_
;
129
_heap_
=
from
.
_heap_
;
130
_nb_elements_
=
from
.
_nb_elements_
;
131
132
// restore the link between _indices_ and _heap_
133
for
(
const
auto
&
elt
:
_indices_
) {
134
_heap_
[
elt
.
second
].
second
= &(
elt
.
first
);
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
>
151
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>&
152
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
operator
=(
153
const
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
OtherAlloc
,
Gen
>&
from
) {
154
GUM_OP_CPY
(
PriorityQueueImplementation
);
155
156
try
{
157
// set the comprison function
158
_cmp_
=
from
.
_cmp_
;
159
160
// copy the indices and the heap
161
_indices_
=
from
.
_indices_
;
162
_nb_elements_
=
from
.
_nb_elements_
;
163
164
_heap_
.
clear
();
165
if
(
_nb_elements_
) {
166
_heap_
.
reserve
(
from
.
_heap_
.
size
());
167
for
(
const
auto
&
elt
:
from
.
_heap_
) {
168
_heap_
.
push_back
(
elt
);
169
}
170
for
(
const
auto
&
elt
:
_indices_
) {
171
_heap_
[
elt
.
second
].
second
= &(
elt
.
first
);
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
>
187
INLINE
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>&
188
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
operator
=(
189
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>&&
from
) {
190
// avoid self assignment
191
if
(
this
!= &
from
) {
192
GUM_OP_MOV
(
PriorityQueueImplementation
)
193
194
_indices_
=
std
::
move
(
from
.
_indices_
);
195
_heap_
=
std
::
move
(
from
.
_heap_
);
196
_cmp_
=
std
::
move
(
from
.
_cmp_
);
197
_nb_elements_
=
std
::
move
(
from
.
_nb_elements_
);
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
>
205
INLINE
const
Val
&
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
top
()
const
{
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
&
214
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
topPriority
()
const
{
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
>
222
INLINE
Size
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
size
()
const
noexcept
{
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
229
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
capacity
()
const
noexcept
{
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
>
235
INLINE
void
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
resize
(
Size
new_size
) {
236
if
(
new_size
<
_nb_elements_
)
return
;
237
238
_heap_
.
reserve
(
new_size
);
239
_indices_
.
resize
(
new_size
/ 2);
240
}
241
242
// removes all the elements from the queue
243
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
,
bool
Gen
>
244
INLINE
void
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
clear
() {
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
>
252
void
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
eraseByPos
(
Size
index
) {
253
if
(
index
>=
_nb_elements_
)
return
;
254
255
// remove the element from the hashtable
256
_indices_
.
erase
(*(
_heap_
[
index
].
second
));
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
>
287
INLINE
void
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
erase
(
const
Val
&
val
) {
288
try
{
289
eraseByPos
(
_indices_
[
val
]);
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
>
295
INLINE
void
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
eraseTop
() {
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
>
301
INLINE
Val
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
pop
() {
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
>&
313
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
allValues
()
const
noexcept
{
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
>
319
INLINE
Size
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
insert
(
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)
324
typename
HashTable
<
Val
,
Size
,
IndexAllocator
>::
value_type
&
new_elt
=
_indices_
.
insert
(
val
, 0);
325
326
try
{
327
_heap_
.
push_back
(
std
::
pair
<
Priority
,
const
Val
* >(
priority
, &
new_elt
.
first
));
328
}
catch
(...) {
329
_indices_
.
erase
(
val
);
330
throw
;
331
}
332
333
std
::
pair
<
Priority
,
const
Val
* >
new_heap_val
=
std
::
move
(
_heap_
[
_nb_elements_
]);
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
346
_heap_
[
i
].
first
=
std
::
move
(
new_heap_val
.
first
);
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
356
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
insert
(
Val
&&
val
,
357
Priority
&&
priority
) {
358
// create the entry in the indices hashtable (if the element already exists,
359
// _indices_.insert will raise a Duplicateelement exception)
360
typename
HashTable
<
Val
,
Size
,
IndexAllocator
>::
value_type
&
new_elt
361
=
_indices_
.
insert
(
std
::
move
(
val
), 0);
362
363
try
{
364
_heap_
.
push_back
(
std
::
pair
<
Priority
,
const
Val
* >(
std
::
move
(
priority
), &(
new_elt
.
first
)));
365
}
catch
(...) {
366
_indices_
.
erase
(
new_elt
.
first
);
367
throw
;
368
}
369
370
std
::
pair
<
Priority
,
const
Val
* >
new_heap_val
=
std
::
move
(
_heap_
[
_nb_elements_
]);
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
383
_heap_
[
i
].
first
=
std
::
move
(
new_heap_val
.
first
);
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
394
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
emplace
(
Args
&&...
args
) {
395
std
::
pair
<
Val
,
Priority
>
new_elt
396
=
std
::
make_pair
<
Val
,
Priority
>(
std
::
forward
<
Args
>(
args
)...);
397
return
insert
(
std
::
move
(
new_elt
.
first
),
std
::
move
(
new_elt
.
second
));
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
403
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
empty
()
const
noexcept
{
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
410
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
contains
(
const
Val
&
val
)
const
{
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
&
417
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
operator
[](
Size
index
)
const
{
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
>
427
std
::
string
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
toString
()
const
{
428
bool
deja
=
false
;
429
std
::
stringstream
stream
;
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
>
445
Size
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
setPriorityByPos
(
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
480
_heap_
[
i
].
first
=
new_priority
;
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
>
489
Size
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
setPriorityByPos
(
490
Size
index
,
491
Priority
&&
new_priority
) {
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
524
_heap_
[
i
].
first
=
std
::
move
(
new_priority
);
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
>
533
void
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
setPriority
(
534
const
Val
&
elt
,
535
const
Priority
&
new_priority
) {
536
setPriorityByPos
(
_indices_
[
elt
],
new_priority
);
537
}
538
539
// modifies the priority of a given element
540
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
,
bool
Gen
>
541
void
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
setPriority
(
542
const
Val
&
elt
,
543
Priority
&&
new_priority
) {
544
setPriorityByPos
(
_indices_
[
elt
],
std
::
move
(
new_priority
));
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
&
550
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
priority
(
const
Val
&
elt
)
const
{
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
&
557
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
Gen
>::
priorityByPos
(
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
572
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
PriorityQueueImplementation
(
573
Cmp
compare
,
574
Size
capacity
) :
575
_indices_
(
capacity
>> 1,
true
,
true
),
576
_cmp_
(
compare
) {
577
_heap_
.
reserve
(
capacity
);
578
579
// for debugging purposes
580
GUM_CONSTRUCTOR
(
PriorityQueueImplementation
);
581
}
582
583
// initializer list constructor
584
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
585
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
PriorityQueueImplementation
(
586
std
::
initializer_list
<
std
::
pair
<
Val
,
Priority
> >
list
) :
587
_indices_
(
Size
(
list
.
size
()) / 2,
true
,
true
) {
588
// fill the queue
589
_heap_
.
reserve
(
list
.
size
());
590
for
(
const
auto
&
elt
:
list
) {
591
insert
(
elt
.
first
,
elt
.
second
);
592
}
593
594
// for debugging purposes
595
GUM_CONSTRUCTOR
(
PriorityQueueImplementation
);
596
}
597
598
// copy constructor
599
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
600
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
PriorityQueueImplementation
(
601
const
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>&
from
) :
602
_heap_
(
from
.
_heap_
),
603
_indices_
(
from
.
_indices_
),
_nb_elements_
(
from
.
_nb_elements_
),
_cmp_
(
from
.
_cmp_
) {
604
// for debugging purposes
605
GUM_CONS_CPY
(
PriorityQueueImplementation
);
606
}
607
608
// generalized copy constructor
609
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
610
template
<
typename
OtherAlloc
>
611
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
PriorityQueueImplementation
(
612
const
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
OtherAlloc
,
true
>&
from
) :
613
_indices_
(
from
.
_indices_
),
614
_nb_elements_
(
from
.
_nb_elements_
),
_cmp_
(
from
.
_cmp_
) {
615
// fill the heap structure
616
if
(
_nb_elements_
) {
617
_heap_
.
reserve
(
from
.
_heap_
.
size
());
618
for
(
const
auto
&
elt
:
from
.
_heap_
) {
619
_heap_
.
push_back
(
elt
);
620
}
621
}
622
623
// for debugging purposes
624
GUM_CONS_CPY
(
PriorityQueueImplementation
);
625
}
626
627
// move constructor
628
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
629
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
PriorityQueueImplementation
(
630
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>&&
from
) :
631
_heap_
(
std
::
move
(
from
.
_heap_
)),
632
_indices_
(
std
::
move
(
from
.
_indices_
)),
_nb_elements_
(
std
::
move
(
from
.
_nb_elements_
)),
633
_cmp_
(
std
::
move
(
from
.
_cmp_
)) {
634
// for debugging purposes
635
GUM_CONS_MOV
(
PriorityQueueImplementation
);
636
}
637
638
// destructor
639
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
640
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::~
PriorityQueueImplementation
() {
641
// for debugging purposes
642
GUM_DESTRUCTOR
(
PriorityQueueImplementation
);
643
}
644
645
// copy operator
646
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
647
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>&
648
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
operator
=(
649
const
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>&
from
) {
650
// avoid self assignment
651
if
(
this
!= &
from
) {
652
// for debugging purposes
653
GUM_OP_CPY
(
PriorityQueueImplementation
);
654
655
try
{
656
// set the comparison function
657
_cmp_
=
from
.
_cmp_
;
658
659
// copy the indices and the heap
660
_indices_
=
from
.
_indices_
;
661
_heap_
=
from
.
_heap_
;
662
_nb_elements_
=
from
.
_nb_elements_
;
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
>
678
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>&
679
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
operator
=(
680
const
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
OtherAlloc
,
true
>&
from
) {
681
// for debugging purposes
682
GUM_OP_CPY
(
PriorityQueueImplementation
);
683
684
try
{
685
// set the comprison function
686
_cmp_
=
from
.
_cmp_
;
687
688
// copy the indices and the heap
689
_indices_
=
from
.
_indices_
;
690
_nb_elements_
=
from
.
_nb_elements_
;
691
692
_heap_
.
clear
();
693
if
(
_nb_elements_
) {
694
_heap_
.
reserve
(
from
.
_heap_
.
size
());
695
for
(
const
auto
&
elt
:
from
.
_heap_
) {
696
_heap_
.
push_back
(
elt
);
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
>
712
INLINE
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>&
713
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
operator
=(
714
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>&&
from
) {
715
// avoid self assignment
716
if
(
this
!= &
from
) {
717
// for debugging purposes
718
GUM_OP_MOV
(
PriorityQueueImplementation
);
719
720
_indices_
=
std
::
move
(
from
.
_indices_
);
721
_heap_
=
std
::
move
(
from
.
_heap_
);
722
_cmp_
=
std
::
move
(
from
.
_cmp_
);
723
_nb_elements_
=
std
::
move
(
from
.
_nb_elements_
);
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
&
740
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
topPriority
()
const
{
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
763
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
resize
(
Size
new_size
) {
764
if
(
new_size
<
_nb_elements_
)
return
;
765
766
_heap_
.
reserve
(
new_size
);
767
_indices_
.
resize
(
new_size
/ 2);
768
}
769
770
// removes all the elements from the queue
771
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
772
INLINE
void
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
clear
() {
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
>
780
void
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
eraseByPos
(
Size
index
) {
781
if
(
index
>=
_nb_elements_
)
return
;
782
783
// remove the element from the hashtable
784
_indices_
.
erase
(
_heap_
[
index
].
second
);
785
786
// put the last element at the "index" location
787
std
::
pair
<
Priority
,
Val
>
last
=
std
::
move
(
_heap_
[
_nb_elements_
- 1]);
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
>
815
INLINE
void
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
erase
(
Val
val
) {
816
try
{
817
eraseByPos
(
_indices_
[
val
]);
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
>
823
INLINE
void
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
eraseTop
() {
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
>
829
INLINE
Val
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
pop
() {
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
>
847
INLINE
Size
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
insert
(
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)
852
typename
HashTable
<
Val
,
Size
,
IndexAllocator
>::
value_type
&
new_elt
=
_indices_
.
insert
(
val
, 0);
853
854
try
{
855
_heap_
.
push_back
(
std
::
pair
<
Priority
,
Val
>(
priority
,
val
));
856
}
catch
(...) {
857
_indices_
.
erase
(
val
);
858
throw
;
859
}
860
861
std
::
pair
<
Priority
,
Val
>
new_heap_val
=
std
::
move
(
_heap_
[
_nb_elements_
]);
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
874
_heap_
[
i
].
first
=
std
::
move
(
new_heap_val
.
first
);
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
884
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
insert
(
Val
val
,
885
Priority
&&
priority
) {
886
// create the entry in the indices hashtable (if the element already exists,
887
// _indices_.insert will raise a Duplicateelement exception)
888
typename
HashTable
<
Val
,
Size
,
IndexAllocator
>::
value_type
&
new_elt
=
_indices_
.
insert
(
val
, 0);
889
890
try
{
891
_heap_
.
push_back
(
std
::
pair
<
Priority
,
Val
>(
std
::
move
(
priority
),
val
));
892
}
catch
(...) {
893
_indices_
.
erase
(
val
);
894
throw
;
895
}
896
897
std
::
pair
<
Priority
,
Val
>
new_heap_val
=
std
::
move
(
_heap_
[
_nb_elements_
]);
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
910
_heap_
[
i
].
first
=
std
::
move
(
new_heap_val
.
first
);
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
921
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
emplace
(
Args
&&...
args
) {
922
std
::
pair
<
Val
,
Priority
>
new_elt
923
=
std
::
make_pair
<
Val
,
Priority
>(
std
::
forward
<
Args
>(
args
)...);
924
return
insert
(
new_elt
.
first
,
std
::
move
(
new_elt
.
second
));
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
937
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
contains
(
Val
val
)
const
{
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
&
944
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
operator
[](
Size
index
)
const
{
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
>
954
std
::
string
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
toString
()
const
{
955
bool
deja
=
false
;
956
std
::
stringstream
stream
;
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
>
972
Size
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
setPriorityByPos
(
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
981
Val
val
=
_heap_
[
index
].
second
;
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
1007
_heap_
[
i
].
first
=
new_priority
;
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
>
1016
Size
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
setPriorityByPos
(
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
1051
_heap_
[
i
].
first
=
std
::
move
(
new_priority
);
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
>
1060
void
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
setPriority
(
1061
Val
elt
,
1062
const
Priority
&
new_priority
) {
1063
setPriorityByPos
(
_indices_
[
elt
],
new_priority
);
1064
}
1065
1066
// modifies the priority of a given element
1067
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
1068
void
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
setPriority
(
1069
Val
elt
,
1070
Priority
&&
new_priority
) {
1071
setPriorityByPos
(
_indices_
[
elt
],
std
::
move
(
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
&
1077
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
priority
(
Val
elt
)
const
{
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
&
1084
PriorityQueueImplementation
<
Val
,
Priority
,
Cmp
,
Alloc
,
true
>::
priorityByPos
(
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
>
1098
INLINE
PriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
PriorityQueue
(
Cmp
cmp
,
Size
capacity
) :
1099
PriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
Implementation
(
cmp
,
capacity
) {
1100
// for debugging purposes
1101
GUM_CONSTRUCTOR
(
PriorityQueue
);
1102
}
1103
1104
// initializer list constructor
1105
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
1106
INLINE
PriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
PriorityQueue
(
1107
std
::
initializer_list
<
std
::
pair
<
Val
,
Priority
> >
list
) :
1108
PriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
Implementation
{
list
} {
1109
// for debugging purposes
1110
GUM_CONSTRUCTOR
(
PriorityQueue
);
1111
}
1112
1113
// copy constructor
1114
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
1115
INLINE
PriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
PriorityQueue
(
1116
const
PriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>&
from
) :
1117
PriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
Implementation
(
from
) {
1118
// for debugging purposes
1119
GUM_CONS_CPY
(
PriorityQueue
);
1120
}
1121
1122
// generalized copy constructor
1123
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
1124
template
<
typename
OtherAlloc
>
1125
INLINE
PriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
PriorityQueue
(
1126
const
PriorityQueue
<
Val
,
Priority
,
Cmp
,
OtherAlloc
>&
from
) :
1127
PriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
Implementation
(
from
) {
1128
// for debugging purposes
1129
GUM_CONS_CPY
(
PriorityQueue
);
1130
}
1131
1132
// move constructor
1133
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
1134
INLINE
PriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
PriorityQueue
(
1135
PriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>&&
from
) :
1136
PriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
Implementation
(
std
::
move
(
from
)) {
1137
// for debugging purposes
1138
GUM_CONS_MOV
(
PriorityQueue
);
1139
}
1140
1141
// destructor
1142
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
1143
INLINE
PriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::~
PriorityQueue
() {
1144
// for debugging purposes
1145
GUM_DESTRUCTOR
(
PriorityQueue
);
1146
}
1147
1148
// copy operator
1149
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
1150
INLINE
PriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>&
1151
PriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
operator
=(
1152
const
PriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>&
from
) {
1153
Implementation
::
operator
=(
from
);
1154
return
*
this
;
1155
}
1156
1157
// generalized copy operator
1158
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
1159
template
<
typename
OtherAlloc
>
1160
INLINE
PriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>&
1161
PriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
operator
=(
1162
const
PriorityQueue
<
Val
,
Priority
,
Cmp
,
OtherAlloc
>&
from
) {
1163
Implementation
::
operator
=(
from
);
1164
return
*
this
;
1165
}
1166
1167
// move operator
1168
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
1169
INLINE
PriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>&
1170
PriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>::
operator
=(
1171
PriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>&&
from
) {
1172
Implementation
::
operator
=(
std
::
move
(
from
));
1173
return
*
this
;
1174
}
1175
1176
// A \c << operator for priority queues
1177
template
<
typename
Val
,
typename
Priority
,
typename
Cmp
,
typename
Alloc
>
1178
INLINE
std
::
ostream
&
operator
<<(
std
::
ostream
&
stream
,
1179
const
PriorityQueue
<
Val
,
Priority
,
Cmp
,
Alloc
>&
queue
) {
1180
stream
<<
queue
.
toString
();
1181
return
stream
;
1182
}
1183
1184
}
/* namespace gum */
gum::Set::emplace
INLINE void emplace(Args &&... args)
Definition:
set_tpl.h:643