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 
63 namespace 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
80  using _IterTraits = iterator_traits<_RandomAccessIterator>;
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  {
103  typename iterator_traits<_RandomAccessIterator>::difference_type __d(__n);
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  {
114  typename iterator_traits<_RandomAccessIterator>::difference_type __d(__n);
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  {
260  typedef typename iterator_traits<_RandomAccessIterator>::value_type
261  _ValueType;
262  typedef typename iterator_traits<_RandomAccessIterator>::difference_type
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 */
constexpr _RandomAccessIterator is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp)
Search the end of a heap using comparison functor.
Definition: stl_heap.h:523
constexpr iterator_traits< _InputIterator >::difference_type distance(_InputIterator __first, _InputIterator __last)
A generalization of pointer arithmetic.
One of the comparison functors.
Definition: stl_function.h:594
Traits class for iterators.
ISO C++ entities toplevel namespace is std.