1 // Heap implementation -*- C++ -*-
3 // Copyright (C) 2001-2013 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>
61 namespace std
_GLIBCXX_VISIBILITY(default)
63 _GLIBCXX_BEGIN_NAMESPACE_VERSION
66 * @defgroup heap_algorithms Heap
67 * @ingroup sorting_algorithms
70 template<typename _RandomAccessIterator
, typename _Distance
>
72 __is_heap_until(_RandomAccessIterator __first
, _Distance __n
)
74 _Distance __parent
= 0;
75 for (_Distance __child
= 1; __child
< __n
; ++__child
)
77 if (__first
[__parent
] < __first
[__child
])
79 if ((__child
& 1) == 0)
85 template<typename _RandomAccessIterator
, typename _Distance
,
88 __is_heap_until(_RandomAccessIterator __first
, _Distance __n
,
91 _Distance __parent
= 0;
92 for (_Distance __child
= 1; __child
< __n
; ++__child
)
94 if (__comp(__first
[__parent
], __first
[__child
]))
96 if ((__child
& 1) == 0)
102 // __is_heap, a predicate testing whether or not a range is a heap.
103 // This function is an extension, not part of the C++ standard.
104 template<typename _RandomAccessIterator
, typename _Distance
>
106 __is_heap(_RandomAccessIterator __first
, _Distance __n
)
107 { return std::__is_heap_until(__first
, __n
) == __n
; }
109 template<typename _RandomAccessIterator
, typename _Compare
,
112 __is_heap(_RandomAccessIterator __first
, _Compare __comp
, _Distance __n
)
113 { return std::__is_heap_until(__first
, __n
, __comp
) == __n
; }
115 template<typename _RandomAccessIterator
>
117 __is_heap(_RandomAccessIterator __first
, _RandomAccessIterator __last
)
118 { return std::__is_heap(__first
, std::distance(__first
, __last
)); }
120 template<typename _RandomAccessIterator
, typename _Compare
>
122 __is_heap(_RandomAccessIterator __first
, _RandomAccessIterator __last
,
124 { return std::__is_heap(__first
, __comp
, std::distance(__first
, __last
)); }
126 // Heap-manipulation functions: push_heap, pop_heap, make_heap, sort_heap,
127 // + is_heap and is_heap_until in C++0x.
129 template<typename _RandomAccessIterator
, typename _Distance
, typename _Tp
>
131 __push_heap(_RandomAccessIterator __first
,
132 _Distance __holeIndex
, _Distance __topIndex
, _Tp __value
)
134 _Distance __parent
= (__holeIndex
- 1) / 2;
135 while (__holeIndex
> __topIndex
&& *(__first
+ __parent
) < __value
)
137 *(__first
+ __holeIndex
) = _GLIBCXX_MOVE(*(__first
+ __parent
));
138 __holeIndex
= __parent
;
139 __parent
= (__holeIndex
- 1) / 2;
141 *(__first
+ __holeIndex
) = _GLIBCXX_MOVE(__value
);
145 * @brief Push an element onto a heap.
146 * @param __first Start of heap.
147 * @param __last End of heap + element.
148 * @ingroup heap_algorithms
150 * This operation pushes the element at last-1 onto the valid heap
151 * over the range [__first,__last-1). After completion,
152 * [__first,__last) is a valid heap.
154 template<typename _RandomAccessIterator
>
156 push_heap(_RandomAccessIterator __first
, _RandomAccessIterator __last
)
158 typedef typename iterator_traits
<_RandomAccessIterator
>::value_type
160 typedef typename iterator_traits
<_RandomAccessIterator
>::difference_type
163 // concept requirements
164 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept
<
165 _RandomAccessIterator
>)
166 __glibcxx_function_requires(_LessThanComparableConcept
<_ValueType
>)
167 __glibcxx_requires_valid_range(__first
, __last
);
168 __glibcxx_requires_heap(__first
, __last
- 1);
170 _ValueType __value
= _GLIBCXX_MOVE(*(__last
- 1));
171 std::__push_heap(__first
, _DistanceType((__last
- __first
) - 1),
172 _DistanceType(0), _GLIBCXX_MOVE(__value
));
175 template<typename _RandomAccessIterator
, typename _Distance
, typename _Tp
,
178 __push_heap(_RandomAccessIterator __first
, _Distance __holeIndex
,
179 _Distance __topIndex
, _Tp __value
, _Compare __comp
)
181 _Distance __parent
= (__holeIndex
- 1) / 2;
182 while (__holeIndex
> __topIndex
183 && __comp(*(__first
+ __parent
), __value
))
185 *(__first
+ __holeIndex
) = _GLIBCXX_MOVE(*(__first
+ __parent
));
186 __holeIndex
= __parent
;
187 __parent
= (__holeIndex
- 1) / 2;
189 *(__first
+ __holeIndex
) = _GLIBCXX_MOVE(__value
);
193 * @brief Push an element onto a heap using comparison functor.
194 * @param __first Start of heap.
195 * @param __last End of heap + element.
196 * @param __comp Comparison functor.
197 * @ingroup heap_algorithms
199 * This operation pushes the element at __last-1 onto the valid
200 * heap over the range [__first,__last-1). After completion,
201 * [__first,__last) is a valid heap. Compare operations are
202 * performed using comp.
204 template<typename _RandomAccessIterator
, typename _Compare
>
206 push_heap(_RandomAccessIterator __first
, _RandomAccessIterator __last
,
209 typedef typename iterator_traits
<_RandomAccessIterator
>::value_type
211 typedef typename iterator_traits
<_RandomAccessIterator
>::difference_type
214 // concept requirements
215 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept
<
216 _RandomAccessIterator
>)
217 __glibcxx_requires_valid_range(__first
, __last
);
218 __glibcxx_requires_heap_pred(__first
, __last
- 1, __comp
);
220 _ValueType __value
= _GLIBCXX_MOVE(*(__last
- 1));
221 std::__push_heap(__first
, _DistanceType((__last
- __first
) - 1),
222 _DistanceType(0), _GLIBCXX_MOVE(__value
), __comp
);
225 template<typename _RandomAccessIterator
, typename _Distance
, typename _Tp
>
227 __adjust_heap(_RandomAccessIterator __first
, _Distance __holeIndex
,
228 _Distance __len
, _Tp __value
)
230 const _Distance __topIndex
= __holeIndex
;
231 _Distance __secondChild
= __holeIndex
;
232 while (__secondChild
< (__len
- 1) / 2)
234 __secondChild
= 2 * (__secondChild
+ 1);
235 if (*(__first
+ __secondChild
) < *(__first
+ (__secondChild
- 1)))
237 *(__first
+ __holeIndex
) = _GLIBCXX_MOVE(*(__first
+ __secondChild
));
238 __holeIndex
= __secondChild
;
240 if ((__len
& 1) == 0 && __secondChild
== (__len
- 2) / 2)
242 __secondChild
= 2 * (__secondChild
+ 1);
243 *(__first
+ __holeIndex
) = _GLIBCXX_MOVE(*(__first
244 + (__secondChild
- 1)));
245 __holeIndex
= __secondChild
- 1;
247 std::__push_heap(__first
, __holeIndex
, __topIndex
,
248 _GLIBCXX_MOVE(__value
));
251 template<typename _RandomAccessIterator
>
253 __pop_heap(_RandomAccessIterator __first
, _RandomAccessIterator __last
,
254 _RandomAccessIterator __result
)
256 typedef typename iterator_traits
<_RandomAccessIterator
>::value_type
258 typedef typename iterator_traits
<_RandomAccessIterator
>::difference_type
261 _ValueType __value
= _GLIBCXX_MOVE(*__result
);
262 *__result
= _GLIBCXX_MOVE(*__first
);
263 std::__adjust_heap(__first
, _DistanceType(0),
264 _DistanceType(__last
- __first
),
265 _GLIBCXX_MOVE(__value
));
269 * @brief Pop an element off a heap.
270 * @param __first Start of heap.
271 * @param __last End of heap.
272 * @pre [__first, __last) is a valid, non-empty range.
273 * @ingroup heap_algorithms
275 * This operation pops the top of the heap. The elements __first
276 * and __last-1 are swapped and [__first,__last-1) is made into a
279 template<typename _RandomAccessIterator
>
281 pop_heap(_RandomAccessIterator __first
, _RandomAccessIterator __last
)
283 typedef typename iterator_traits
<_RandomAccessIterator
>::value_type
286 // concept requirements
287 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept
<
288 _RandomAccessIterator
>)
289 __glibcxx_function_requires(_LessThanComparableConcept
<_ValueType
>)
290 __glibcxx_requires_non_empty_range(__first
, __last
);
291 __glibcxx_requires_valid_range(__first
, __last
);
292 __glibcxx_requires_heap(__first
, __last
);
295 std::__pop_heap(__first
, __last
, __last
);
298 template<typename _RandomAccessIterator
, typename _Distance
,
299 typename _Tp
, typename _Compare
>
301 __adjust_heap(_RandomAccessIterator __first
, _Distance __holeIndex
,
302 _Distance __len
, _Tp __value
, _Compare __comp
)
304 const _Distance __topIndex
= __holeIndex
;
305 _Distance __secondChild
= __holeIndex
;
306 while (__secondChild
< (__len
- 1) / 2)
308 __secondChild
= 2 * (__secondChild
+ 1);
309 if (__comp(*(__first
+ __secondChild
),
310 *(__first
+ (__secondChild
- 1))))
312 *(__first
+ __holeIndex
) = _GLIBCXX_MOVE(*(__first
+ __secondChild
));
313 __holeIndex
= __secondChild
;
315 if ((__len
& 1) == 0 && __secondChild
== (__len
- 2) / 2)
317 __secondChild
= 2 * (__secondChild
+ 1);
318 *(__first
+ __holeIndex
) = _GLIBCXX_MOVE(*(__first
319 + (__secondChild
- 1)));
320 __holeIndex
= __secondChild
- 1;
322 std::__push_heap(__first
, __holeIndex
, __topIndex
,
323 _GLIBCXX_MOVE(__value
), __comp
);
326 template<typename _RandomAccessIterator
, typename _Compare
>
328 __pop_heap(_RandomAccessIterator __first
, _RandomAccessIterator __last
,
329 _RandomAccessIterator __result
, _Compare __comp
)
331 typedef typename iterator_traits
<_RandomAccessIterator
>::value_type
333 typedef typename iterator_traits
<_RandomAccessIterator
>::difference_type
336 _ValueType __value
= _GLIBCXX_MOVE(*__result
);
337 *__result
= _GLIBCXX_MOVE(*__first
);
338 std::__adjust_heap(__first
, _DistanceType(0),
339 _DistanceType(__last
- __first
),
340 _GLIBCXX_MOVE(__value
), __comp
);
344 * @brief Pop an element off a heap using comparison functor.
345 * @param __first Start of heap.
346 * @param __last End of heap.
347 * @param __comp Comparison functor to use.
348 * @ingroup heap_algorithms
350 * This operation pops the top of the heap. The elements __first
351 * and __last-1 are swapped and [__first,__last-1) is made into a
352 * heap. Comparisons are made using comp.
354 template<typename _RandomAccessIterator
, typename _Compare
>
356 pop_heap(_RandomAccessIterator __first
,
357 _RandomAccessIterator __last
, _Compare __comp
)
359 // concept requirements
360 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept
<
361 _RandomAccessIterator
>)
362 __glibcxx_requires_valid_range(__first
, __last
);
363 __glibcxx_requires_non_empty_range(__first
, __last
);
364 __glibcxx_requires_heap_pred(__first
, __last
, __comp
);
367 std::__pop_heap(__first
, __last
, __last
, __comp
);
371 * @brief Construct a heap over a range.
372 * @param __first Start of heap.
373 * @param __last End of heap.
374 * @ingroup heap_algorithms
376 * This operation makes the elements in [__first,__last) into a heap.
378 template<typename _RandomAccessIterator
>
380 make_heap(_RandomAccessIterator __first
, _RandomAccessIterator __last
)
382 typedef typename iterator_traits
<_RandomAccessIterator
>::value_type
384 typedef typename iterator_traits
<_RandomAccessIterator
>::difference_type
387 // concept requirements
388 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept
<
389 _RandomAccessIterator
>)
390 __glibcxx_function_requires(_LessThanComparableConcept
<_ValueType
>)
391 __glibcxx_requires_valid_range(__first
, __last
);
393 if (__last
- __first
< 2)
396 const _DistanceType __len
= __last
- __first
;
397 _DistanceType __parent
= (__len
- 2) / 2;
400 _ValueType __value
= _GLIBCXX_MOVE(*(__first
+ __parent
));
401 std::__adjust_heap(__first
, __parent
, __len
, _GLIBCXX_MOVE(__value
));
409 * @brief Construct a heap over a range using comparison functor.
410 * @param __first Start of heap.
411 * @param __last End of heap.
412 * @param __comp Comparison functor to use.
413 * @ingroup heap_algorithms
415 * This operation makes the elements in [__first,__last) into a heap.
416 * Comparisons are made using __comp.
418 template<typename _RandomAccessIterator
, typename _Compare
>
420 make_heap(_RandomAccessIterator __first
, _RandomAccessIterator __last
,
423 typedef typename iterator_traits
<_RandomAccessIterator
>::value_type
425 typedef typename iterator_traits
<_RandomAccessIterator
>::difference_type
428 // concept requirements
429 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept
<
430 _RandomAccessIterator
>)
431 __glibcxx_requires_valid_range(__first
, __last
);
433 if (__last
- __first
< 2)
436 const _DistanceType __len
= __last
- __first
;
437 _DistanceType __parent
= (__len
- 2) / 2;
440 _ValueType __value
= _GLIBCXX_MOVE(*(__first
+ __parent
));
441 std::__adjust_heap(__first
, __parent
, __len
, _GLIBCXX_MOVE(__value
),
450 * @brief Sort a heap.
451 * @param __first Start of heap.
452 * @param __last End of heap.
453 * @ingroup heap_algorithms
455 * This operation sorts the valid heap in the range [__first,__last).
457 template<typename _RandomAccessIterator
>
459 sort_heap(_RandomAccessIterator __first
, _RandomAccessIterator __last
)
461 // concept requirements
462 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept
<
463 _RandomAccessIterator
>)
464 __glibcxx_function_requires(_LessThanComparableConcept
<
465 typename iterator_traits
<_RandomAccessIterator
>::value_type
>)
466 __glibcxx_requires_valid_range(__first
, __last
);
467 __glibcxx_requires_heap(__first
, __last
);
469 while (__last
- __first
> 1)
472 std::__pop_heap(__first
, __last
, __last
);
477 * @brief Sort a heap using comparison functor.
478 * @param __first Start of heap.
479 * @param __last End of heap.
480 * @param __comp Comparison functor to use.
481 * @ingroup heap_algorithms
483 * This operation sorts the valid heap in the range [__first,__last).
484 * Comparisons are made using __comp.
486 template<typename _RandomAccessIterator
, typename _Compare
>
488 sort_heap(_RandomAccessIterator __first
, _RandomAccessIterator __last
,
491 // concept requirements
492 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept
<
493 _RandomAccessIterator
>)
494 __glibcxx_requires_valid_range(__first
, __last
);
495 __glibcxx_requires_heap_pred(__first
, __last
, __comp
);
497 while (__last
- __first
> 1)
500 std::__pop_heap(__first
, __last
, __last
, __comp
);
504 #if __cplusplus >= 201103L
506 * @brief Search the end of a heap.
507 * @param __first Start of range.
508 * @param __last End of range.
509 * @return An iterator pointing to the first element not in the heap.
510 * @ingroup heap_algorithms
512 * This operation returns the last iterator i in [__first, __last) for which
513 * the range [__first, i) is a heap.
515 template<typename _RandomAccessIterator
>
516 inline _RandomAccessIterator
517 is_heap_until(_RandomAccessIterator __first
, _RandomAccessIterator __last
)
519 // concept requirements
520 __glibcxx_function_requires(_RandomAccessIteratorConcept
<
521 _RandomAccessIterator
>)
522 __glibcxx_function_requires(_LessThanComparableConcept
<
523 typename iterator_traits
<_RandomAccessIterator
>::value_type
>)
524 __glibcxx_requires_valid_range(__first
, __last
);
526 return __first
+ std::__is_heap_until(__first
, std::distance(__first
,
531 * @brief Search the end of a heap using comparison functor.
532 * @param __first Start of range.
533 * @param __last End of range.
534 * @param __comp Comparison functor to use.
535 * @return An iterator pointing to the first element not in the heap.
536 * @ingroup heap_algorithms
538 * This operation returns the last iterator i in [__first, __last) for which
539 * the range [__first, i) is a heap. Comparisons are made using __comp.
541 template<typename _RandomAccessIterator
, typename _Compare
>
542 inline _RandomAccessIterator
543 is_heap_until(_RandomAccessIterator __first
, _RandomAccessIterator __last
,
546 // concept requirements
547 __glibcxx_function_requires(_RandomAccessIteratorConcept
<
548 _RandomAccessIterator
>)
549 __glibcxx_requires_valid_range(__first
, __last
);
551 return __first
+ std::__is_heap_until(__first
, std::distance(__first
,
557 * @brief Determines whether a range is a heap.
558 * @param __first Start of range.
559 * @param __last End of range.
560 * @return True if range is a heap, false otherwise.
561 * @ingroup heap_algorithms
563 template<typename _RandomAccessIterator
>
565 is_heap(_RandomAccessIterator __first
, _RandomAccessIterator __last
)
566 { return std::is_heap_until(__first
, __last
) == __last
; }
569 * @brief Determines whether a range is a heap using comparison functor.
570 * @param __first Start of range.
571 * @param __last End of range.
572 * @param __comp Comparison functor to use.
573 * @return True if range is a heap, false otherwise.
574 * @ingroup heap_algorithms
576 template<typename _RandomAccessIterator
, typename _Compare
>
578 is_heap(_RandomAccessIterator __first
, _RandomAccessIterator __last
,
580 { return std::is_heap_until(__first
, __last
, __comp
) == __last
; }
583 _GLIBCXX_END_NAMESPACE_VERSION
586 #endif /* _STL_HEAP_H */