1 // Heap implementation -*- C++ -*-
3 // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
4 // Free Software Foundation, Inc.
6 // This file is part of the GNU ISO C++ Library. This library is free
7 // software; you can redistribute it and/or modify it under the
8 // terms of the GNU General Public License as published by the
9 // Free Software Foundation; either version 3, or (at your option)
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
17 // Under Section 7 of GPL version 3, you are granted additional
18 // permissions described in the GCC Runtime Library Exception, version
19 // 3.1, as published by the Free Software Foundation.
21 // You should have received a copy of the GNU General Public License and
22 // a copy of the GCC Runtime Library Exception along with this program;
23 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 // <http://www.gnu.org/licenses/>.
29 * Hewlett-Packard Company
31 * Permission to use, copy, modify, distribute and sell this software
32 * and its documentation for any purpose is hereby granted without fee,
33 * provided that the above copyright notice appear in all copies and
34 * that both that copyright notice and this permission notice appear
35 * in supporting documentation. Hewlett-Packard Company makes no
36 * representations about the suitability of this software for any
37 * purpose. It is provided "as is" without express or implied warranty.
40 * Silicon Graphics Computer Systems, Inc.
42 * Permission to use, copy, modify, distribute and sell this software
43 * and its documentation for any purpose is hereby granted without fee,
44 * provided that the above copyright notice appear in all copies and
45 * that both that copyright notice and this permission notice appear
46 * in supporting documentation. Silicon Graphics makes no
47 * representations about the suitability of this software for any
48 * purpose. It is provided "as is" without express or implied warranty.
51 /** @file bits/stl_heap.h
52 * This is an internal header file, included by other library headers.
53 * Do not attempt to use it directly. @headername{queue}
59 #include <debug/debug.h>
60 #include <bits/move.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>
73 __is_heap_until(_RandomAccessIterator __first, _Distance __n)
75 _Distance __parent = 0;
76 for (_Distance __child = 1; __child < __n; ++__child)
78 if (__first[__parent] < __first[__child])
80 if ((__child & 1) == 0)
86 template<typename _RandomAccessIterator, typename _Distance,
89 __is_heap_until(_RandomAccessIterator __first, _Distance __n,
92 _Distance __parent = 0;
93 for (_Distance __child = 1; __child < __n; ++__child)
95 if (__comp(__first[__parent], __first[__child]))
97 if ((__child & 1) == 0)
103 // __is_heap, a predicate testing whether or not a range is a heap.
104 // This function is an extension, not part of the C++ standard.
105 template<typename _RandomAccessIterator, typename _Distance>
107 __is_heap(_RandomAccessIterator __first, _Distance __n)
108 { return std::__is_heap_until(__first, __n) == __n; }
110 template<typename _RandomAccessIterator, typename _Compare,
113 __is_heap(_RandomAccessIterator __first, _Compare __comp, _Distance __n)
114 { return std::__is_heap_until(__first, __n, __comp) == __n; }
116 template<typename _RandomAccessIterator>
118 __is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
119 { return std::__is_heap(__first, std::distance(__first, __last)); }
121 template<typename _RandomAccessIterator, typename _Compare>
123 __is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
125 { return std::__is_heap(__first, __comp, std::distance(__first, __last)); }
127 // Heap-manipulation functions: push_heap, pop_heap, make_heap, sort_heap,
128 // + is_heap and is_heap_until in C++0x.
130 template<typename _RandomAccessIterator, typename _Distance, typename _Tp>
132 __push_heap(_RandomAccessIterator __first,
133 _Distance __holeIndex, _Distance __topIndex, _Tp __value)
135 _Distance __parent = (__holeIndex - 1) / 2;
136 while (__holeIndex > __topIndex && *(__first + __parent) < __value)
138 *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __parent));
139 __holeIndex = __parent;
140 __parent = (__holeIndex - 1) / 2;
142 *(__first + __holeIndex) = _GLIBCXX_MOVE(__value);
146 * @brief Push an element onto a heap.
147 * @param first Start of heap.
148 * @param last End of heap + element.
149 * @ingroup heap_algorithms
151 * This operation pushes the element at last-1 onto the valid heap over the
152 * range [first,last-1). After completion, [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 heap over the
200 * range [first,last-1). After completion, [first,last) is a valid heap.
201 * Compare operations are performed using comp.
203 template<typename _RandomAccessIterator, typename _Compare>
205 push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
208 typedef typename iterator_traits<_RandomAccessIterator>::value_type
210 typedef typename iterator_traits<_RandomAccessIterator>::difference_type
213 // concept requirements
214 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
215 _RandomAccessIterator>)
216 __glibcxx_requires_valid_range(__first, __last);
217 __glibcxx_requires_heap_pred(__first, __last - 1, __comp);
219 _ValueType __value = _GLIBCXX_MOVE(*(__last - 1));
220 std::__push_heap(__first, _DistanceType((__last - __first) - 1),
221 _DistanceType(0), _GLIBCXX_MOVE(__value), __comp);
224 template<typename _RandomAccessIterator, typename _Distance, typename _Tp>
226 __adjust_heap(_RandomAccessIterator __first, _Distance __holeIndex,
227 _Distance __len, _Tp __value)
229 const _Distance __topIndex = __holeIndex;
230 _Distance __secondChild = __holeIndex;
231 while (__secondChild < (__len - 1) / 2)
233 __secondChild = 2 * (__secondChild + 1);
234 if (*(__first + __secondChild) < *(__first + (__secondChild - 1)))
236 *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __secondChild));
237 __holeIndex = __secondChild;
239 if ((__len & 1) == 0 && __secondChild == (__len - 2) / 2)
241 __secondChild = 2 * (__secondChild + 1);
242 *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first
243 + (__secondChild - 1)));
244 __holeIndex = __secondChild - 1;
246 std::__push_heap(__first, __holeIndex, __topIndex,
247 _GLIBCXX_MOVE(__value));
250 template<typename _RandomAccessIterator>
252 __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
253 _RandomAccessIterator __result)
255 typedef typename iterator_traits<_RandomAccessIterator>::value_type
257 typedef typename iterator_traits<_RandomAccessIterator>::difference_type
260 _ValueType __value = _GLIBCXX_MOVE(*__result);
261 *__result = _GLIBCXX_MOVE(*__first);
262 std::__adjust_heap(__first, _DistanceType(0),
263 _DistanceType(__last - __first),
264 _GLIBCXX_MOVE(__value));
268 * @brief Pop an element off a heap.
269 * @param first Start of heap.
270 * @param last End of heap.
271 * @ingroup heap_algorithms
273 * This operation pops the top of the heap. The elements first and last-1
274 * are swapped and [first,last-1) is made into a heap.
276 template<typename _RandomAccessIterator>
278 pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
280 typedef typename iterator_traits<_RandomAccessIterator>::value_type
283 // concept requirements
284 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
285 _RandomAccessIterator>)
286 __glibcxx_function_requires(_LessThanComparableConcept<_ValueType>)
287 __glibcxx_requires_valid_range(__first, __last);
288 __glibcxx_requires_heap(__first, __last);
291 std::__pop_heap(__first, __last, __last);
294 template<typename _RandomAccessIterator, typename _Distance,
295 typename _Tp, typename _Compare>
297 __adjust_heap(_RandomAccessIterator __first, _Distance __holeIndex,
298 _Distance __len, _Tp __value, _Compare __comp)
300 const _Distance __topIndex = __holeIndex;
301 _Distance __secondChild = __holeIndex;
302 while (__secondChild < (__len - 1) / 2)
304 __secondChild = 2 * (__secondChild + 1);
305 if (__comp(*(__first + __secondChild),
306 *(__first + (__secondChild - 1))))
308 *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __secondChild));
309 __holeIndex = __secondChild;
311 if ((__len & 1) == 0 && __secondChild == (__len - 2) / 2)
313 __secondChild = 2 * (__secondChild + 1);
314 *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first
315 + (__secondChild - 1)));
316 __holeIndex = __secondChild - 1;
318 std::__push_heap(__first, __holeIndex, __topIndex,
319 _GLIBCXX_MOVE(__value), __comp);
322 template<typename _RandomAccessIterator, typename _Compare>
324 __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
325 _RandomAccessIterator __result, _Compare __comp)
327 typedef typename iterator_traits<_RandomAccessIterator>::value_type
329 typedef typename iterator_traits<_RandomAccessIterator>::difference_type
332 _ValueType __value = _GLIBCXX_MOVE(*__result);
333 *__result = _GLIBCXX_MOVE(*__first);
334 std::__adjust_heap(__first, _DistanceType(0),
335 _DistanceType(__last - __first),
336 _GLIBCXX_MOVE(__value), __comp);
340 * @brief Pop an element off a heap using comparison functor.
341 * @param first Start of heap.
342 * @param last End of heap.
343 * @param comp Comparison functor to use.
344 * @ingroup heap_algorithms
346 * This operation pops the top of the heap. The elements first and last-1
347 * are swapped and [first,last-1) is made into a heap. Comparisons are
350 template<typename _RandomAccessIterator, typename _Compare>
352 pop_heap(_RandomAccessIterator __first,
353 _RandomAccessIterator __last, _Compare __comp)
355 // concept requirements
356 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
357 _RandomAccessIterator>)
358 __glibcxx_requires_valid_range(__first, __last);
359 __glibcxx_requires_heap_pred(__first, __last, __comp);
362 std::__pop_heap(__first, __last, __last, __comp);
366 * @brief Construct a heap over a range.
367 * @param first Start of heap.
368 * @param last End of heap.
369 * @ingroup heap_algorithms
371 * This operation makes the elements in [first,last) into a heap.
373 template<typename _RandomAccessIterator>
375 make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
377 typedef typename iterator_traits<_RandomAccessIterator>::value_type
379 typedef typename iterator_traits<_RandomAccessIterator>::difference_type
382 // concept requirements
383 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
384 _RandomAccessIterator>)
385 __glibcxx_function_requires(_LessThanComparableConcept<_ValueType>)
386 __glibcxx_requires_valid_range(__first, __last);
388 if (__last - __first < 2)
391 const _DistanceType __len = __last - __first;
392 _DistanceType __parent = (__len - 2) / 2;
395 _ValueType __value = _GLIBCXX_MOVE(*(__first + __parent));
396 std::__adjust_heap(__first, __parent, __len, _GLIBCXX_MOVE(__value));
404 * @brief Construct a heap over a range using comparison functor.
405 * @param first Start of heap.
406 * @param last End of heap.
407 * @param comp Comparison functor to use.
408 * @ingroup heap_algorithms
410 * This operation makes the elements in [first,last) into a heap.
411 * Comparisons are made using comp.
413 template<typename _RandomAccessIterator, typename _Compare>
415 make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
418 typedef typename iterator_traits<_RandomAccessIterator>::value_type
420 typedef typename iterator_traits<_RandomAccessIterator>::difference_type
423 // concept requirements
424 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
425 _RandomAccessIterator>)
426 __glibcxx_requires_valid_range(__first, __last);
428 if (__last - __first < 2)
431 const _DistanceType __len = __last - __first;
432 _DistanceType __parent = (__len - 2) / 2;
435 _ValueType __value = _GLIBCXX_MOVE(*(__first + __parent));
436 std::__adjust_heap(__first, __parent, __len, _GLIBCXX_MOVE(__value),
445 * @brief Sort a heap.
446 * @param first Start of heap.
447 * @param last End of heap.
448 * @ingroup heap_algorithms
450 * This operation sorts the valid heap in the range [first,last).
452 template<typename _RandomAccessIterator>
454 sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
456 // concept requirements
457 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
458 _RandomAccessIterator>)
459 __glibcxx_function_requires(_LessThanComparableConcept<
460 typename iterator_traits<_RandomAccessIterator>::value_type>)
461 __glibcxx_requires_valid_range(__first, __last);
462 __glibcxx_requires_heap(__first, __last);
464 while (__last - __first > 1)
467 std::__pop_heap(__first, __last, __last);
472 * @brief Sort a heap using comparison functor.
473 * @param first Start of heap.
474 * @param last End of heap.
475 * @param comp Comparison functor to use.
476 * @ingroup heap_algorithms
478 * This operation sorts the valid heap in the range [first,last).
479 * Comparisons are made using comp.
481 template<typename _RandomAccessIterator, typename _Compare>
483 sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
486 // concept requirements
487 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
488 _RandomAccessIterator>)
489 __glibcxx_requires_valid_range(__first, __last);
490 __glibcxx_requires_heap_pred(__first, __last, __comp);
492 while (__last - __first > 1)
495 std::__pop_heap(__first, __last, __last, __comp);
499 #ifdef __GXX_EXPERIMENTAL_CXX0X__
501 * @brief Search the end of a heap.
502 * @param first Start of range.
503 * @param last End of range.
504 * @return An iterator pointing to the first element not in the heap.
505 * @ingroup heap_algorithms
507 * This operation returns the last iterator i in [first, last) for which
508 * the range [first, i) is a heap.
510 template<typename _RandomAccessIterator>
511 inline _RandomAccessIterator
512 is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last)
514 // concept requirements
515 __glibcxx_function_requires(_RandomAccessIteratorConcept<
516 _RandomAccessIterator>)
517 __glibcxx_function_requires(_LessThanComparableConcept<
518 typename iterator_traits<_RandomAccessIterator>::value_type>)
519 __glibcxx_requires_valid_range(__first, __last);
521 return __first + std::__is_heap_until(__first, std::distance(__first,
526 * @brief Search the end of a heap using comparison functor.
527 * @param first Start of range.
528 * @param last End of range.
529 * @param comp Comparison functor to use.
530 * @return An iterator pointing to the first element not in the heap.
531 * @ingroup heap_algorithms
533 * This operation returns the last iterator i in [first, last) for which
534 * the range [first, i) is a heap. Comparisons are made using comp.
536 template<typename _RandomAccessIterator, typename _Compare>
537 inline _RandomAccessIterator
538 is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last,
541 // concept requirements
542 __glibcxx_function_requires(_RandomAccessIteratorConcept<
543 _RandomAccessIterator>)
544 __glibcxx_requires_valid_range(__first, __last);
546 return __first + std::__is_heap_until(__first, std::distance(__first,
552 * @brief Determines whether a range is a heap.
553 * @param first Start of range.
554 * @param last End of range.
555 * @return True if range is a heap, false otherwise.
556 * @ingroup heap_algorithms
558 template<typename _RandomAccessIterator>
560 is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
561 { return std::is_heap_until(__first, __last) == __last; }
564 * @brief Determines whether a range is a heap using comparison functor.
565 * @param first Start of range.
566 * @param last End of range.
567 * @param comp Comparison functor to use.
568 * @return True if range is a heap, false otherwise.
569 * @ingroup heap_algorithms
571 template<typename _RandomAccessIterator, typename _Compare>
573 is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
575 { return std::is_heap_until(__first, __last, __comp) == __last; }
578 _GLIBCXX_END_NAMESPACE_VERSION
581 #endif /* _STL_HEAP_H */