libstdc++
stl_heap.h
Go to the documentation of this file.
1// Heap implementation -*- C++ -*-
2
3// Copyright (C) 2001-2026 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// 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 General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25/*
26 *
27 * Copyright (c) 1994
28 * Hewlett-Packard Company
29 *
30 * Permission to use, copy, modify, distribute and sell this software
31 * and its documentation for any purpose is hereby granted without fee,
32 * provided that the above copyright notice appear in all copies and
33 * that both that copyright notice and this permission notice appear
34 * in supporting documentation. Hewlett-Packard Company makes no
35 * representations about the suitability of this software for any
36 * purpose. It is provided "as is" without express or implied warranty.
37 *
38 * Copyright (c) 1997
39 * Silicon Graphics Computer Systems, Inc.
40 *
41 * Permission to use, copy, modify, distribute and sell this software
42 * and its documentation for any purpose is hereby granted without fee,
43 * provided that the above copyright notice appear in all copies and
44 * that both that copyright notice and this permission notice appear
45 * in supporting documentation. Silicon Graphics makes no
46 * representations about the suitability of this software for any
47 * purpose. It is provided "as is" without express or implied warranty.
48 */
49
50/** @file bits/stl_heap.h
51 * This is an internal header file, included by other library headers.
52 * Do not attempt to use it directly. @headername{queue}
53 */
54
55#ifndef _STL_HEAP_H
56#define _STL_HEAP_H 1
57
58#include <debug/debug.h>
59#include <bits/move.h>
60#include <bits/predefined_ops.h>
62
63namespace std _GLIBCXX_VISIBILITY(default)
64{
65_GLIBCXX_BEGIN_NAMESPACE_VERSION
66
67 /**
68 * @defgroup heap_algorithms Heap
69 * @ingroup sorting_algorithms
70 */
71
72 template<typename _RandomAccessIterator, typename _Distance,
73 typename _Compare>
74 _GLIBCXX20_CONSTEXPR
75 _Distance
76 __is_heap_until(_RandomAccessIterator __first, _Distance __n,
77 _Compare& __comp)
78 {
79#if __cplusplus >= 201103L
81 static_assert(is_same<typename _IterTraits::difference_type,
82 _Distance>::value,
83 "Argument 'n' must be the iterator's difference type");
84#endif
85 _Distance __parent = 0;
86 for (_Distance __child = 1; __child < __n; ++__child)
87 {
88 if (__comp(*(__first + __parent), *(__first + __child)))
89 return __child;
90 if ((__child & 1) == 0)
91 ++__parent;
92 }
93 return __n;
94 }
95
96 // __is_heap, a predicate testing whether or not a range is a heap.
97 // This function is an extension, not part of the C++ standard.
98 template<typename _RandomAccessIterator, typename _Distance>
99 _GLIBCXX20_CONSTEXPR
100 inline bool
101 __is_heap(_RandomAccessIterator __first, _Distance __n)
102 {
104 __gnu_cxx::__ops::less __comp;
105 return std::__is_heap_until(__first, __d, __comp) == __n;
106 }
107
108 template<typename _RandomAccessIterator, typename _Compare,
109 typename _Distance>
110 _GLIBCXX20_CONSTEXPR
111 inline bool
112 __is_heap(_RandomAccessIterator __first, _Compare __comp, _Distance __n)
113 {
115 return std::__is_heap_until(__first, __d, __comp) == __n;
116 }
117
118 template<typename _RandomAccessIterator>
119 _GLIBCXX20_CONSTEXPR
120 inline bool
121 __is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
122 { return std::__is_heap(__first, std::distance(__first, __last)); }
123
124 template<typename _RandomAccessIterator, typename _Compare>
125 _GLIBCXX20_CONSTEXPR
126 inline bool
127 __is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
128 _Compare __comp)
129 {
130 return std::__is_heap(__first, _GLIBCXX_MOVE(__comp),
131 std::distance(__first, __last));
132 }
133
134 // Heap-manipulation functions: push_heap, pop_heap, make_heap, sort_heap,
135 // + is_heap and is_heap_until in C++0x.
136
137 template<typename _RandomAccessIterator, typename _Distance, typename _Tp,
138 typename _Compare>
139 _GLIBCXX20_CONSTEXPR
140 void
141 __push_heap(_RandomAccessIterator __first,
142 _Distance __holeIndex, _Distance __topIndex, _Tp __value,
143 _Compare& __comp)
144 {
145 _Distance __parent = (__holeIndex - 1) / 2;
146 while (__holeIndex > __topIndex
147 && bool(__comp(*(__first + __parent), __value)))
148 {
149 *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __parent));
150 __holeIndex = __parent;
151 __parent = (__holeIndex - 1) / 2;
152 }
153 *(__first + __holeIndex) = _GLIBCXX_MOVE(__value);
154 }
155
156 /**
157 * @brief Push an element onto a heap.
158 * @param __first Start of heap.
159 * @param __last End of heap + element.
160 * @ingroup heap_algorithms
161 *
162 * This operation pushes the element at last-1 onto the valid heap
163 * over the range [__first,__last-1). After completion,
164 * [__first,__last) is a valid heap.
165 */
166 template<typename _RandomAccessIterator>
167 _GLIBCXX20_CONSTEXPR
168 inline void
169 push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
170 {
172 _ValueType;
174 _DistanceType;
175
176 // concept requirements
177 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
178 _RandomAccessIterator>)
179 __glibcxx_function_requires(_LessThanComparableConcept<_ValueType>)
180 __glibcxx_requires_valid_range(__first, __last);
181 __glibcxx_requires_irreflexive(__first, __last);
182 __glibcxx_requires_heap(__first, __last - _DistanceType(1));
183
184 __gnu_cxx::__ops::less __comp;
185 _ValueType __value = _GLIBCXX_MOVE(*(__last - _DistanceType(1)));
186 std::__push_heap(__first, _DistanceType((__last - __first) - 1),
187 _DistanceType(0), _GLIBCXX_MOVE(__value), __comp);
188 }
189
190 /**
191 * @brief Push an element onto a heap using comparison functor.
192 * @param __first Start of heap.
193 * @param __last End of heap + element.
194 * @param __comp Comparison functor.
195 * @ingroup heap_algorithms
196 *
197 * This operation pushes the element at __last-1 onto the valid
198 * heap over the range [__first,__last-1). After completion,
199 * [__first,__last) is a valid heap. Compare operations are
200 * performed using comp.
201 */
202 template<typename _RandomAccessIterator, typename _Compare>
203 _GLIBCXX20_CONSTEXPR
204 inline void
205 push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
206 _Compare __comp)
207 {
209 _ValueType;
211 _DistanceType;
212
213 // concept requirements
214 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
215 _RandomAccessIterator>)
216 __glibcxx_requires_valid_range(__first, __last);
217 __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
218 __glibcxx_requires_heap_pred(__first, __last - _DistanceType(1), __comp);
219
220 _ValueType __value = _GLIBCXX_MOVE(*(__last - _DistanceType(1)));
221 std::__push_heap(__first, _DistanceType((__last - __first) - 1),
222 _DistanceType(0), _GLIBCXX_MOVE(__value), __comp);
223 }
224
225 template<typename _RandomAccessIterator, typename _Distance,
226 typename _Tp, typename _Compare>
227 _GLIBCXX20_CONSTEXPR
228 void
229 __adjust_heap(_RandomAccessIterator __first, _Distance __holeIndex,
230 _Distance __len, _Tp __value, _Compare __comp)
231 {
232 const _Distance __topIndex = __holeIndex;
233 _Distance __secondChild = __holeIndex;
234 while (__secondChild < (__len - 1) / 2)
235 {
236 __secondChild = 2 * (__secondChild + 1);
237 if (__comp(*(__first + __secondChild),
238 *(__first + _Distance(__secondChild - 1))))
239 __secondChild--;
240 *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __secondChild));
241 __holeIndex = __secondChild;
242 }
243 if ((__len & 1) == 0 && __secondChild == (__len - 2) / 2)
244 {
245 __secondChild = 2 * (__secondChild + 1);
246 *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first
247 + (__secondChild - 1)));
248 __holeIndex = __secondChild - 1;
249 }
250 std::__push_heap(__first, __holeIndex, __topIndex,
251 _GLIBCXX_MOVE(__value), __comp);
252 }
253
254 template<typename _RandomAccessIterator, typename _Compare>
255 _GLIBCXX20_CONSTEXPR
256 inline void
257 __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
258 _RandomAccessIterator __result, _Compare& __comp)
259 {
261 _ValueType;
263 _DistanceType;
264
265 _ValueType __value = _GLIBCXX_MOVE(*__result);
266 *__result = _GLIBCXX_MOVE(*__first);
267 std::__adjust_heap(__first, _DistanceType(0),
268 _DistanceType(__last - __first),
269 _GLIBCXX_MOVE(__value), __comp);
270 }
271
272 /**
273 * @brief Pop an element off a heap.
274 * @param __first Start of heap.
275 * @param __last End of heap.
276 * @pre [__first, __last) is a valid, non-empty range.
277 * @ingroup heap_algorithms
278 *
279 * This operation pops the top of the heap. The elements __first
280 * and __last-1 are swapped and [__first,__last-1) is made into a
281 * heap.
282 */
283 template<typename _RandomAccessIterator>
284 _GLIBCXX20_CONSTEXPR
285 inline void
286 pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
287 {
288 // concept requirements
289 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
290 _RandomAccessIterator>)
291 __glibcxx_function_requires(_LessThanComparableConcept<
293 __glibcxx_requires_non_empty_range(__first, __last);
294 __glibcxx_requires_valid_range(__first, __last);
295 __glibcxx_requires_irreflexive(__first, __last);
296 __glibcxx_requires_heap(__first, __last);
297
298 if (__last - __first > 1)
299 {
300 --__last;
301 __gnu_cxx::__ops::less __comp;
302 std::__pop_heap(__first, __last, __last, __comp);
303 }
304 }
305
306 /**
307 * @brief Pop an element off a heap using comparison functor.
308 * @param __first Start of heap.
309 * @param __last End of heap.
310 * @param __comp Comparison functor to use.
311 * @ingroup heap_algorithms
312 *
313 * This operation pops the top of the heap. The elements __first
314 * and __last-1 are swapped and [__first,__last-1) is made into a
315 * heap. Comparisons are made using comp.
316 */
317 template<typename _RandomAccessIterator, typename _Compare>
318 _GLIBCXX20_CONSTEXPR
319 inline void
320 pop_heap(_RandomAccessIterator __first,
321 _RandomAccessIterator __last, _Compare __comp)
322 {
323 // concept requirements
324 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
325 _RandomAccessIterator>)
326 __glibcxx_requires_valid_range(__first, __last);
327 __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
328 __glibcxx_requires_non_empty_range(__first, __last);
329 __glibcxx_requires_heap_pred(__first, __last, __comp);
330
331 if (__last - __first > 1)
332 {
333 --__last;
334 std::__pop_heap(__first, __last, __last, __comp);
335 }
336 }
337
338 template<typename _RandomAccessIterator, typename _Compare>
339 _GLIBCXX20_CONSTEXPR
340 void
341 __make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
342 _Compare& __comp)
343 {
344 typedef typename iterator_traits<_RandomAccessIterator>::value_type
345 _ValueType;
346 typedef typename iterator_traits<_RandomAccessIterator>::difference_type
347 _DistanceType;
348
349 if (__last - __first < 2)
350 return;
351
352 const _DistanceType __len = __last - __first;
353 _DistanceType __parent = (__len - 2) / 2;
354 while (true)
355 {
356 _ValueType __value = _GLIBCXX_MOVE(*(__first + __parent));
357 std::__adjust_heap(__first, __parent, __len, _GLIBCXX_MOVE(__value),
358 __comp);
359 if (__parent == 0)
360 return;
361 __parent--;
362 }
363 }
364
365 /**
366 * @brief Construct a heap over a range.
367 * @param __first Start of heap.
368 * @param __last End of heap.
369 * @ingroup heap_algorithms
370 *
371 * This operation makes the elements in [__first,__last) into a heap.
372 */
373 template<typename _RandomAccessIterator>
374 _GLIBCXX20_CONSTEXPR
375 inline void
376 make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
377 {
378 // concept requirements
379 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
380 _RandomAccessIterator>)
381 __glibcxx_function_requires(_LessThanComparableConcept<
383 __glibcxx_requires_valid_range(__first, __last);
384 __glibcxx_requires_irreflexive(__first, __last);
385
386 __gnu_cxx::__ops::less __comp;
387 std::__make_heap(__first, __last, __comp);
388 }
389
390 /**
391 * @brief Construct a heap over a range using comparison functor.
392 * @param __first Start of heap.
393 * @param __last End of heap.
394 * @param __comp Comparison functor to use.
395 * @ingroup heap_algorithms
396 *
397 * This operation makes the elements in [__first,__last) into a heap.
398 * Comparisons are made using __comp.
399 */
400 template<typename _RandomAccessIterator, typename _Compare>
401 _GLIBCXX20_CONSTEXPR
402 inline void
403 make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
404 _Compare __comp)
405 {
406 // concept requirements
407 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
408 _RandomAccessIterator>)
409 __glibcxx_requires_valid_range(__first, __last);
410 __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
411
412 std::__make_heap(__first, __last, __comp);
413 }
414
415 template<typename _RandomAccessIterator, typename _Compare>
416 _GLIBCXX20_CONSTEXPR
417 void
418 __sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
419 _Compare& __comp)
420 {
421 while (__last - __first > 1)
422 {
423 --__last;
424 std::__pop_heap(__first, __last, __last, __comp);
425 }
426 }
427
428 /**
429 * @brief Sort a heap.
430 * @param __first Start of heap.
431 * @param __last End of heap.
432 * @ingroup heap_algorithms
433 *
434 * This operation sorts the valid heap in the range [__first,__last).
435 */
436 template<typename _RandomAccessIterator>
437 _GLIBCXX20_CONSTEXPR
438 inline void
439 sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
440 {
441 // concept requirements
442 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
443 _RandomAccessIterator>)
444 __glibcxx_function_requires(_LessThanComparableConcept<
446 __glibcxx_requires_valid_range(__first, __last);
447 __glibcxx_requires_irreflexive(__first, __last);
448 __glibcxx_requires_heap(__first, __last);
449
450 __gnu_cxx::__ops::less __comp;
451 std::__sort_heap(__first, __last, __comp);
452 }
453
454 /**
455 * @brief Sort a heap using comparison functor.
456 * @param __first Start of heap.
457 * @param __last End of heap.
458 * @param __comp Comparison functor to use.
459 * @ingroup heap_algorithms
460 *
461 * This operation sorts the valid heap in the range [__first,__last).
462 * Comparisons are made using __comp.
463 */
464 template<typename _RandomAccessIterator, typename _Compare>
465 _GLIBCXX20_CONSTEXPR
466 inline void
467 sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
468 _Compare __comp)
469 {
470 // concept requirements
471 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
472 _RandomAccessIterator>)
473 __glibcxx_requires_valid_range(__first, __last);
474 __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
475 __glibcxx_requires_heap_pred(__first, __last, __comp);
476
477 std::__sort_heap(__first, __last, __comp);
478 }
479
480#if __cplusplus >= 201103L
481 /**
482 * @brief Search the end of a heap.
483 * @param __first Start of range.
484 * @param __last End of range.
485 * @return An iterator pointing to the first element not in the heap.
486 * @ingroup heap_algorithms
487 *
488 * This operation returns the last iterator i in [__first, __last) for which
489 * the range [__first, i) is a heap.
490 */
491 template<typename _RandomAccessIterator>
492 _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
493 inline _RandomAccessIterator
494 is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last)
495 {
496 // concept requirements
497 __glibcxx_function_requires(_RandomAccessIteratorConcept<
498 _RandomAccessIterator>)
499 __glibcxx_function_requires(_LessThanComparableConcept<
501 __glibcxx_requires_valid_range(__first, __last);
502 __glibcxx_requires_irreflexive(__first, __last);
503
504 __gnu_cxx::__ops::less __comp;
505 return __first +
506 std::__is_heap_until(__first, std::distance(__first, __last), __comp);
507 }
508
509 /**
510 * @brief Search the end of a heap using comparison functor.
511 * @param __first Start of range.
512 * @param __last End of range.
513 * @param __comp Comparison functor to use.
514 * @return An iterator pointing to the first element not in the heap.
515 * @ingroup heap_algorithms
516 *
517 * This operation returns the last iterator i in [__first, __last) for which
518 * the range [__first, i) is a heap. Comparisons are made using __comp.
519 */
520 template<typename _RandomAccessIterator, typename _Compare>
521 _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
522 inline _RandomAccessIterator
523 is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last,
524 _Compare __comp)
525 {
526 // concept requirements
527 __glibcxx_function_requires(_RandomAccessIteratorConcept<
528 _RandomAccessIterator>)
529 __glibcxx_requires_valid_range(__first, __last);
530 __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
531
532 return __first
533 + std::__is_heap_until(__first, std::distance(__first, __last),
534 __comp);
535 }
536
537 /**
538 * @brief Determines whether a range is a heap.
539 * @param __first Start of range.
540 * @param __last End of range.
541 * @return True if range is a heap, false otherwise.
542 * @ingroup heap_algorithms
543 */
544 template<typename _RandomAccessIterator>
545 _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
546 inline bool
547 is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
548 { return std::is_heap_until(__first, __last) == __last; }
549
550 /**
551 * @brief Determines whether a range is a heap using comparison functor.
552 * @param __first Start of range.
553 * @param __last End of range.
554 * @param __comp Comparison functor to use.
555 * @return True if range is a heap, false otherwise.
556 * @ingroup heap_algorithms
557 */
558 template<typename _RandomAccessIterator, typename _Compare>
559 _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
560 inline bool
561 is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
562 _Compare __comp)
563 {
564 // concept requirements
565 __glibcxx_function_requires(_RandomAccessIteratorConcept<
566 _RandomAccessIterator>)
567 __glibcxx_requires_valid_range(__first, __last);
568 __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
569
570 const auto __dist = std::distance(__first, __last);
571 return std::__is_heap_until(__first, __dist, __comp) == __dist;
572 }
573#endif
574
575_GLIBCXX_END_NAMESPACE_VERSION
576} // namespace
577
578#endif /* _STL_HEAP_H */
ISO C++ entities toplevel namespace is std.
constexpr iterator_traits< _InputIterator >::difference_type distance(_InputIterator __first, _InputIterator __last)
A generalization of pointer arithmetic.
Traits class for iterators.