1 // Heap implementation -*- C++ -*-
3 // Copyright (C) 2001-2018 Free Software Foundation, Inc.
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)
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.
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.
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/>.
28 * Hewlett-Packard Company
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.
39 * Silicon Graphics Computer Systems, Inc.
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.
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}
58 #include <debug/debug.h>
59 #include <bits/move.h>
60 #include <bits/predefined_ops.h>
62 namespace std
_GLIBCXX_VISIBILITY(default)
64 _GLIBCXX_BEGIN_NAMESPACE_VERSION
67 * @defgroup heap_algorithms Heap
68 * @ingroup sorting_algorithms
71 template<typename _RandomAccessIterator
, typename _Distance
,
74 __is_heap_until(_RandomAccessIterator __first
, _Distance __n
,
77 _Distance __parent
= 0;
78 for (_Distance __child
= 1; __child
< __n
; ++__child
)
80 if (__comp(__first
+ __parent
, __first
+ __child
))
82 if ((__child
& 1) == 0)
88 // __is_heap, a predicate testing whether or not a range is a heap.
89 // This function is an extension, not part of the C++ standard.
90 template<typename _RandomAccessIterator
, typename _Distance
>
92 __is_heap(_RandomAccessIterator __first
, _Distance __n
)
94 __gnu_cxx::__ops::_Iter_less_iter __comp
;
95 return std::__is_heap_until(__first
, __n
, __comp
) == __n
;
98 template<typename _RandomAccessIterator
, typename _Compare
,
101 __is_heap(_RandomAccessIterator __first
, _Compare __comp
, _Distance __n
)
103 typedef __decltype(__comp
) _Cmp
;
104 __gnu_cxx::__ops::_Iter_comp_iter
<_Cmp
> __cmp(_GLIBCXX_MOVE(__comp
));
105 return std::__is_heap_until(__first
, __n
, __cmp
) == __n
;
108 template<typename _RandomAccessIterator
>
110 __is_heap(_RandomAccessIterator __first
, _RandomAccessIterator __last
)
111 { return std::__is_heap(__first
, std::distance(__first
, __last
)); }
113 template<typename _RandomAccessIterator
, typename _Compare
>
115 __is_heap(_RandomAccessIterator __first
, _RandomAccessIterator __last
,
118 return std::__is_heap(__first
, _GLIBCXX_MOVE(__comp
),
119 std::distance(__first
, __last
));
122 // Heap-manipulation functions: push_heap, pop_heap, make_heap, sort_heap,
123 // + is_heap and is_heap_until in C++0x.
125 template<typename _RandomAccessIterator
, typename _Distance
, typename _Tp
,
128 __push_heap(_RandomAccessIterator __first
,
129 _Distance __holeIndex
, _Distance __topIndex
, _Tp __value
,
132 _Distance __parent
= (__holeIndex
- 1) / 2;
133 while (__holeIndex
> __topIndex
&& __comp(__first
+ __parent
, __value
))
135 *(__first
+ __holeIndex
) = _GLIBCXX_MOVE(*(__first
+ __parent
));
136 __holeIndex
= __parent
;
137 __parent
= (__holeIndex
- 1) / 2;
139 *(__first
+ __holeIndex
) = _GLIBCXX_MOVE(__value
);
143 * @brief Push an element onto a heap.
144 * @param __first Start of heap.
145 * @param __last End of heap + element.
146 * @ingroup heap_algorithms
148 * This operation pushes the element at last-1 onto the valid heap
149 * over the range [__first,__last-1). After completion,
150 * [__first,__last) is a valid heap.
152 template<typename _RandomAccessIterator
>
154 push_heap(_RandomAccessIterator __first
, _RandomAccessIterator __last
)
156 typedef typename iterator_traits
<_RandomAccessIterator
>::value_type
158 typedef typename iterator_traits
<_RandomAccessIterator
>::difference_type
161 // concept requirements
162 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept
<
163 _RandomAccessIterator
>)
164 __glibcxx_function_requires(_LessThanComparableConcept
<_ValueType
>)
165 __glibcxx_requires_valid_range(__first
, __last
);
166 __glibcxx_requires_irreflexive(__first
, __last
);
167 __glibcxx_requires_heap(__first
, __last
- 1);
169 __gnu_cxx::__ops::_Iter_less_val __comp
;
170 _ValueType __value
= _GLIBCXX_MOVE(*(__last
- 1));
171 std::__push_heap(__first
, _DistanceType((__last
- __first
) - 1),
172 _DistanceType(0), _GLIBCXX_MOVE(__value
), __comp
);
176 * @brief Push an element onto a heap using comparison functor.
177 * @param __first Start of heap.
178 * @param __last End of heap + element.
179 * @param __comp Comparison functor.
180 * @ingroup heap_algorithms
182 * This operation pushes the element at __last-1 onto the valid
183 * heap over the range [__first,__last-1). After completion,
184 * [__first,__last) is a valid heap. Compare operations are
185 * performed using comp.
187 template<typename _RandomAccessIterator
, typename _Compare
>
189 push_heap(_RandomAccessIterator __first
, _RandomAccessIterator __last
,
192 typedef typename iterator_traits
<_RandomAccessIterator
>::value_type
194 typedef typename iterator_traits
<_RandomAccessIterator
>::difference_type
197 // concept requirements
198 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept
<
199 _RandomAccessIterator
>)
200 __glibcxx_requires_valid_range(__first
, __last
);
201 __glibcxx_requires_irreflexive_pred(__first
, __last
, __comp
);
202 __glibcxx_requires_heap_pred(__first
, __last
- 1, __comp
);
204 __decltype(__gnu_cxx::__ops::__iter_comp_val(_GLIBCXX_MOVE(__comp
)))
205 __cmp(_GLIBCXX_MOVE(__comp
));
206 _ValueType __value
= _GLIBCXX_MOVE(*(__last
- 1));
207 std::__push_heap(__first
, _DistanceType((__last
- __first
) - 1),
208 _DistanceType(0), _GLIBCXX_MOVE(__value
), __cmp
);
211 template<typename _RandomAccessIterator
, typename _Distance
,
212 typename _Tp
, typename _Compare
>
214 __adjust_heap(_RandomAccessIterator __first
, _Distance __holeIndex
,
215 _Distance __len
, _Tp __value
, _Compare __comp
)
217 const _Distance __topIndex
= __holeIndex
;
218 _Distance __secondChild
= __holeIndex
;
219 while (__secondChild
< (__len
- 1) / 2)
221 __secondChild
= 2 * (__secondChild
+ 1);
222 if (__comp(__first
+ __secondChild
,
223 __first
+ (__secondChild
- 1)))
225 *(__first
+ __holeIndex
) = _GLIBCXX_MOVE(*(__first
+ __secondChild
));
226 __holeIndex
= __secondChild
;
228 if ((__len
& 1) == 0 && __secondChild
== (__len
- 2) / 2)
230 __secondChild
= 2 * (__secondChild
+ 1);
231 *(__first
+ __holeIndex
) = _GLIBCXX_MOVE(*(__first
232 + (__secondChild
- 1)));
233 __holeIndex
= __secondChild
- 1;
235 __decltype(__gnu_cxx::__ops::__iter_comp_val(_GLIBCXX_MOVE(__comp
)))
236 __cmp(_GLIBCXX_MOVE(__comp
));
237 std::__push_heap(__first
, __holeIndex
, __topIndex
,
238 _GLIBCXX_MOVE(__value
), __cmp
);
241 template<typename _RandomAccessIterator
, typename _Compare
>
243 __pop_heap(_RandomAccessIterator __first
, _RandomAccessIterator __last
,
244 _RandomAccessIterator __result
, _Compare
& __comp
)
246 typedef typename iterator_traits
<_RandomAccessIterator
>::value_type
248 typedef typename iterator_traits
<_RandomAccessIterator
>::difference_type
251 _ValueType __value
= _GLIBCXX_MOVE(*__result
);
252 *__result
= _GLIBCXX_MOVE(*__first
);
253 std::__adjust_heap(__first
, _DistanceType(0),
254 _DistanceType(__last
- __first
),
255 _GLIBCXX_MOVE(__value
), __comp
);
259 * @brief Pop an element off a heap.
260 * @param __first Start of heap.
261 * @param __last End of heap.
262 * @pre [__first, __last) is a valid, non-empty range.
263 * @ingroup heap_algorithms
265 * This operation pops the top of the heap. The elements __first
266 * and __last-1 are swapped and [__first,__last-1) is made into a
269 template<typename _RandomAccessIterator
>
271 pop_heap(_RandomAccessIterator __first
, _RandomAccessIterator __last
)
273 // concept requirements
274 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept
<
275 _RandomAccessIterator
>)
276 __glibcxx_function_requires(_LessThanComparableConcept
<
277 typename iterator_traits
<_RandomAccessIterator
>::value_type
>)
278 __glibcxx_requires_non_empty_range(__first
, __last
);
279 __glibcxx_requires_valid_range(__first
, __last
);
280 __glibcxx_requires_irreflexive(__first
, __last
);
281 __glibcxx_requires_heap(__first
, __last
);
283 if (__last
- __first
> 1)
286 __gnu_cxx::__ops::_Iter_less_iter __comp
;
287 std::__pop_heap(__first
, __last
, __last
, __comp
);
292 * @brief Pop an element off a heap using comparison functor.
293 * @param __first Start of heap.
294 * @param __last End of heap.
295 * @param __comp Comparison functor to use.
296 * @ingroup heap_algorithms
298 * This operation pops the top of the heap. The elements __first
299 * and __last-1 are swapped and [__first,__last-1) is made into a
300 * heap. Comparisons are made using comp.
302 template<typename _RandomAccessIterator
, typename _Compare
>
304 pop_heap(_RandomAccessIterator __first
,
305 _RandomAccessIterator __last
, _Compare __comp
)
307 // concept requirements
308 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept
<
309 _RandomAccessIterator
>)
310 __glibcxx_requires_valid_range(__first
, __last
);
311 __glibcxx_requires_irreflexive_pred(__first
, __last
, __comp
);
312 __glibcxx_requires_non_empty_range(__first
, __last
);
313 __glibcxx_requires_heap_pred(__first
, __last
, __comp
);
315 if (__last
- __first
> 1)
317 typedef __decltype(__comp
) _Cmp
;
318 __gnu_cxx::__ops::_Iter_comp_iter
<_Cmp
> __cmp(_GLIBCXX_MOVE(__comp
));
320 std::__pop_heap(__first
, __last
, __last
, __cmp
);
324 template<typename _RandomAccessIterator
, typename _Compare
>
326 __make_heap(_RandomAccessIterator __first
, _RandomAccessIterator __last
,
329 typedef typename iterator_traits
<_RandomAccessIterator
>::value_type
331 typedef typename iterator_traits
<_RandomAccessIterator
>::difference_type
334 if (__last
- __first
< 2)
337 const _DistanceType __len
= __last
- __first
;
338 _DistanceType __parent
= (__len
- 2) / 2;
341 _ValueType __value
= _GLIBCXX_MOVE(*(__first
+ __parent
));
342 std::__adjust_heap(__first
, __parent
, __len
, _GLIBCXX_MOVE(__value
),
351 * @brief Construct a heap over a range.
352 * @param __first Start of heap.
353 * @param __last End of heap.
354 * @ingroup heap_algorithms
356 * This operation makes the elements in [__first,__last) into a heap.
358 template<typename _RandomAccessIterator
>
360 make_heap(_RandomAccessIterator __first
, _RandomAccessIterator __last
)
362 // concept requirements
363 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept
<
364 _RandomAccessIterator
>)
365 __glibcxx_function_requires(_LessThanComparableConcept
<
366 typename iterator_traits
<_RandomAccessIterator
>::value_type
>)
367 __glibcxx_requires_valid_range(__first
, __last
);
368 __glibcxx_requires_irreflexive(__first
, __last
);
370 __gnu_cxx::__ops::_Iter_less_iter __comp
;
371 std::__make_heap(__first
, __last
, __comp
);
375 * @brief Construct a heap over a range using comparison functor.
376 * @param __first Start of heap.
377 * @param __last End of heap.
378 * @param __comp Comparison functor to use.
379 * @ingroup heap_algorithms
381 * This operation makes the elements in [__first,__last) into a heap.
382 * Comparisons are made using __comp.
384 template<typename _RandomAccessIterator
, typename _Compare
>
386 make_heap(_RandomAccessIterator __first
, _RandomAccessIterator __last
,
389 // concept requirements
390 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept
<
391 _RandomAccessIterator
>)
392 __glibcxx_requires_valid_range(__first
, __last
);
393 __glibcxx_requires_irreflexive_pred(__first
, __last
, __comp
);
395 typedef __decltype(__comp
) _Cmp
;
396 __gnu_cxx::__ops::_Iter_comp_iter
<_Cmp
> __cmp(_GLIBCXX_MOVE(__comp
));
397 std::__make_heap(__first
, __last
, __cmp
);
400 template<typename _RandomAccessIterator
, typename _Compare
>
402 __sort_heap(_RandomAccessIterator __first
, _RandomAccessIterator __last
,
405 while (__last
- __first
> 1)
408 std::__pop_heap(__first
, __last
, __last
, __comp
);
413 * @brief Sort a heap.
414 * @param __first Start of heap.
415 * @param __last End of heap.
416 * @ingroup heap_algorithms
418 * This operation sorts the valid heap in the range [__first,__last).
420 template<typename _RandomAccessIterator
>
422 sort_heap(_RandomAccessIterator __first
, _RandomAccessIterator __last
)
424 // concept requirements
425 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept
<
426 _RandomAccessIterator
>)
427 __glibcxx_function_requires(_LessThanComparableConcept
<
428 typename iterator_traits
<_RandomAccessIterator
>::value_type
>)
429 __glibcxx_requires_valid_range(__first
, __last
);
430 __glibcxx_requires_irreflexive(__first
, __last
);
431 __glibcxx_requires_heap(__first
, __last
);
433 __gnu_cxx::__ops::_Iter_less_iter __comp
;
434 std::__sort_heap(__first
, __last
, __comp
);
438 * @brief Sort a heap using comparison functor.
439 * @param __first Start of heap.
440 * @param __last End of heap.
441 * @param __comp Comparison functor to use.
442 * @ingroup heap_algorithms
444 * This operation sorts the valid heap in the range [__first,__last).
445 * Comparisons are made using __comp.
447 template<typename _RandomAccessIterator
, typename _Compare
>
449 sort_heap(_RandomAccessIterator __first
, _RandomAccessIterator __last
,
452 // concept requirements
453 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept
<
454 _RandomAccessIterator
>)
455 __glibcxx_requires_valid_range(__first
, __last
);
456 __glibcxx_requires_irreflexive_pred(__first
, __last
, __comp
);
457 __glibcxx_requires_heap_pred(__first
, __last
, __comp
);
459 typedef __decltype(__comp
) _Cmp
;
460 __gnu_cxx::__ops::_Iter_comp_iter
<_Cmp
> __cmp(_GLIBCXX_MOVE(__comp
));
461 std::__sort_heap(__first
, __last
, __cmp
);
464 #if __cplusplus >= 201103L
466 * @brief Search the end of a heap.
467 * @param __first Start of range.
468 * @param __last End of range.
469 * @return An iterator pointing to the first element not in the heap.
470 * @ingroup heap_algorithms
472 * This operation returns the last iterator i in [__first, __last) for which
473 * the range [__first, i) is a heap.
475 template<typename _RandomAccessIterator
>
476 inline _RandomAccessIterator
477 is_heap_until(_RandomAccessIterator __first
, _RandomAccessIterator __last
)
479 // concept requirements
480 __glibcxx_function_requires(_RandomAccessIteratorConcept
<
481 _RandomAccessIterator
>)
482 __glibcxx_function_requires(_LessThanComparableConcept
<
483 typename iterator_traits
<_RandomAccessIterator
>::value_type
>)
484 __glibcxx_requires_valid_range(__first
, __last
);
485 __glibcxx_requires_irreflexive(__first
, __last
);
487 __gnu_cxx::__ops::_Iter_less_iter __comp
;
489 std::__is_heap_until(__first
, std::distance(__first
, __last
), __comp
);
493 * @brief Search the end of a heap using comparison functor.
494 * @param __first Start of range.
495 * @param __last End of range.
496 * @param __comp Comparison functor to use.
497 * @return An iterator pointing to the first element not in the heap.
498 * @ingroup heap_algorithms
500 * This operation returns the last iterator i in [__first, __last) for which
501 * the range [__first, i) is a heap. Comparisons are made using __comp.
503 template<typename _RandomAccessIterator
, typename _Compare
>
504 inline _RandomAccessIterator
505 is_heap_until(_RandomAccessIterator __first
, _RandomAccessIterator __last
,
508 // concept requirements
509 __glibcxx_function_requires(_RandomAccessIteratorConcept
<
510 _RandomAccessIterator
>)
511 __glibcxx_requires_valid_range(__first
, __last
);
512 __glibcxx_requires_irreflexive_pred(__first
, __last
, __comp
);
514 typedef __decltype(__comp
) _Cmp
;
515 __gnu_cxx::__ops::_Iter_comp_iter
<_Cmp
> __cmp(_GLIBCXX_MOVE(__comp
));
517 + std::__is_heap_until(__first
, std::distance(__first
, __last
), __cmp
);
521 * @brief Determines whether a range is a heap.
522 * @param __first Start of range.
523 * @param __last End of range.
524 * @return True if range is a heap, false otherwise.
525 * @ingroup heap_algorithms
527 template<typename _RandomAccessIterator
>
529 is_heap(_RandomAccessIterator __first
, _RandomAccessIterator __last
)
530 { return std::is_heap_until(__first
, __last
) == __last
; }
533 * @brief Determines whether a range is a heap using comparison functor.
534 * @param __first Start of range.
535 * @param __last End of range.
536 * @param __comp Comparison functor to use.
537 * @return True if range is a heap, false otherwise.
538 * @ingroup heap_algorithms
540 template<typename _RandomAccessIterator
, typename _Compare
>
542 is_heap(_RandomAccessIterator __first
, _RandomAccessIterator __last
,
545 // concept requirements
546 __glibcxx_function_requires(_RandomAccessIteratorConcept
<
547 _RandomAccessIterator
>)
548 __glibcxx_requires_valid_range(__first
, __last
);
549 __glibcxx_requires_irreflexive_pred(__first
, __last
, __comp
);
551 const auto __dist
= std::distance(__first
, __last
);
552 typedef __decltype(__comp
) _Cmp
;
553 __gnu_cxx::__ops::_Iter_comp_iter
<_Cmp
> __cmp(_GLIBCXX_MOVE(__comp
));
554 return std::__is_heap_until(__first
, __dist
, __cmp
) == __dist
;
558 _GLIBCXX_END_NAMESPACE_VERSION
561 #endif /* _STL_HEAP_H */