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
152 * over the range [__first,__last-1). After completion,
153 * [__first,__last) is a valid heap.
155 template<typename _RandomAccessIterator>
157 push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
159 typedef typename iterator_traits<_RandomAccessIterator>::value_type
161 typedef typename iterator_traits<_RandomAccessIterator>::difference_type
164 // concept requirements
165 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
166 _RandomAccessIterator>)
167 __glibcxx_function_requires(_LessThanComparableConcept<_ValueType>)
168 __glibcxx_requires_valid_range(__first, __last);
169 __glibcxx_requires_heap(__first, __last - 1);
171 _ValueType __value = _GLIBCXX_MOVE(*(__last - 1));
172 std::__push_heap(__first, _DistanceType((__last - __first) - 1),
173 _DistanceType(0), _GLIBCXX_MOVE(__value));
176 template<typename _RandomAccessIterator, typename _Distance, typename _Tp,
179 __push_heap(_RandomAccessIterator __first, _Distance __holeIndex,
180 _Distance __topIndex, _Tp __value, _Compare __comp)
182 _Distance __parent = (__holeIndex - 1) / 2;
183 while (__holeIndex > __topIndex
184 && __comp(*(__first + __parent), __value))
186 *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __parent));
187 __holeIndex = __parent;
188 __parent = (__holeIndex - 1) / 2;
190 *(__first + __holeIndex) = _GLIBCXX_MOVE(__value);
194 * @brief Push an element onto a heap using comparison functor.
195 * @param __first Start of heap.
196 * @param __last End of heap + element.
197 * @param __comp Comparison functor.
198 * @ingroup heap_algorithms
200 * This operation pushes the element at __last-1 onto the valid
201 * heap over the range [__first,__last-1). After completion,
202 * [__first,__last) is a valid heap. Compare operations are
203 * performed using comp.
205 template<typename _RandomAccessIterator, typename _Compare>
207 push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
210 typedef typename iterator_traits<_RandomAccessIterator>::value_type
212 typedef typename iterator_traits<_RandomAccessIterator>::difference_type
215 // concept requirements
216 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
217 _RandomAccessIterator>)
218 __glibcxx_requires_valid_range(__first, __last);
219 __glibcxx_requires_heap_pred(__first, __last - 1, __comp);
221 _ValueType __value = _GLIBCXX_MOVE(*(__last - 1));
222 std::__push_heap(__first, _DistanceType((__last - __first) - 1),
223 _DistanceType(0), _GLIBCXX_MOVE(__value), __comp);
226 template<typename _RandomAccessIterator, typename _Distance, typename _Tp>
228 __adjust_heap(_RandomAccessIterator __first, _Distance __holeIndex,
229 _Distance __len, _Tp __value)
231 const _Distance __topIndex = __holeIndex;
232 _Distance __secondChild = __holeIndex;
233 while (__secondChild < (__len - 1) / 2)
235 __secondChild = 2 * (__secondChild + 1);
236 if (*(__first + __secondChild) < *(__first + (__secondChild - 1)))
238 *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __secondChild));
239 __holeIndex = __secondChild;
241 if ((__len & 1) == 0 && __secondChild == (__len - 2) / 2)
243 __secondChild = 2 * (__secondChild + 1);
244 *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first
245 + (__secondChild - 1)));
246 __holeIndex = __secondChild - 1;
248 std::__push_heap(__first, __holeIndex, __topIndex,
249 _GLIBCXX_MOVE(__value));
252 template<typename _RandomAccessIterator>
254 __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
255 _RandomAccessIterator __result)
257 typedef typename iterator_traits<_RandomAccessIterator>::value_type
259 typedef typename iterator_traits<_RandomAccessIterator>::difference_type
262 _ValueType __value = _GLIBCXX_MOVE(*__result);
263 *__result = _GLIBCXX_MOVE(*__first);
264 std::__adjust_heap(__first, _DistanceType(0),
265 _DistanceType(__last - __first),
266 _GLIBCXX_MOVE(__value));
270 * @brief Pop an element off a heap.
271 * @param __first Start of heap.
272 * @param __last End of heap.
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_valid_range(__first, __last);
291 __glibcxx_requires_heap(__first, __last);
294 std::__pop_heap(__first, __last, __last);
297 template<typename _RandomAccessIterator, typename _Distance,
298 typename _Tp, typename _Compare>
300 __adjust_heap(_RandomAccessIterator __first, _Distance __holeIndex,
301 _Distance __len, _Tp __value, _Compare __comp)
303 const _Distance __topIndex = __holeIndex;
304 _Distance __secondChild = __holeIndex;
305 while (__secondChild < (__len - 1) / 2)
307 __secondChild = 2 * (__secondChild + 1);
308 if (__comp(*(__first + __secondChild),
309 *(__first + (__secondChild - 1))))
311 *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __secondChild));
312 __holeIndex = __secondChild;
314 if ((__len & 1) == 0 && __secondChild == (__len - 2) / 2)
316 __secondChild = 2 * (__secondChild + 1);
317 *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first
318 + (__secondChild - 1)));
319 __holeIndex = __secondChild - 1;
321 std::__push_heap(__first, __holeIndex, __topIndex,
322 _GLIBCXX_MOVE(__value), __comp);
325 template<typename _RandomAccessIterator, typename _Compare>
327 __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
328 _RandomAccessIterator __result, _Compare __comp)
330 typedef typename iterator_traits<_RandomAccessIterator>::value_type
332 typedef typename iterator_traits<_RandomAccessIterator>::difference_type
335 _ValueType __value = _GLIBCXX_MOVE(*__result);
336 *__result = _GLIBCXX_MOVE(*__first);
337 std::__adjust_heap(__first, _DistanceType(0),
338 _DistanceType(__last - __first),
339 _GLIBCXX_MOVE(__value), __comp);
343 * @brief Pop an element off a heap using comparison functor.
344 * @param __first Start of heap.
345 * @param __last End of heap.
346 * @param __comp Comparison functor to use.
347 * @ingroup heap_algorithms
349 * This operation pops the top of the heap. The elements __first
350 * and __last-1 are swapped and [__first,__last-1) is made into a
351 * heap. Comparisons are made using comp.
353 template<typename _RandomAccessIterator, typename _Compare>
355 pop_heap(_RandomAccessIterator __first,
356 _RandomAccessIterator __last, _Compare __comp)
358 // concept requirements
359 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
360 _RandomAccessIterator>)
361 __glibcxx_requires_valid_range(__first, __last);
362 __glibcxx_requires_heap_pred(__first, __last, __comp);
365 std::__pop_heap(__first, __last, __last, __comp);
369 * @brief Construct a heap over a range.
370 * @param __first Start of heap.
371 * @param __last End of heap.
372 * @ingroup heap_algorithms
374 * This operation makes the elements in [__first,__last) into a heap.
376 template<typename _RandomAccessIterator>
378 make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
380 typedef typename iterator_traits<_RandomAccessIterator>::value_type
382 typedef typename iterator_traits<_RandomAccessIterator>::difference_type
385 // concept requirements
386 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
387 _RandomAccessIterator>)
388 __glibcxx_function_requires(_LessThanComparableConcept<_ValueType>)
389 __glibcxx_requires_valid_range(__first, __last);
391 if (__last - __first < 2)
394 const _DistanceType __len = __last - __first;
395 _DistanceType __parent = (__len - 2) / 2;
398 _ValueType __value = _GLIBCXX_MOVE(*(__first + __parent));
399 std::__adjust_heap(__first, __parent, __len, _GLIBCXX_MOVE(__value));
407 * @brief Construct a heap over a range using comparison functor.
408 * @param __first Start of heap.
409 * @param __last End of heap.
410 * @param __comp Comparison functor to use.
411 * @ingroup heap_algorithms
413 * This operation makes the elements in [__first,__last) into a heap.
414 * Comparisons are made using __comp.
416 template<typename _RandomAccessIterator, typename _Compare>
418 make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
421 typedef typename iterator_traits<_RandomAccessIterator>::value_type
423 typedef typename iterator_traits<_RandomAccessIterator>::difference_type
426 // concept requirements
427 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
428 _RandomAccessIterator>)
429 __glibcxx_requires_valid_range(__first, __last);
431 if (__last - __first < 2)
434 const _DistanceType __len = __last - __first;
435 _DistanceType __parent = (__len - 2) / 2;
438 _ValueType __value = _GLIBCXX_MOVE(*(__first + __parent));
439 std::__adjust_heap(__first, __parent, __len, _GLIBCXX_MOVE(__value),
448 * @brief Sort a heap.
449 * @param __first Start of heap.
450 * @param __last End of heap.
451 * @ingroup heap_algorithms
453 * This operation sorts the valid heap in the range [__first,__last).
455 template<typename _RandomAccessIterator>
457 sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
459 // concept requirements
460 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
461 _RandomAccessIterator>)
462 __glibcxx_function_requires(_LessThanComparableConcept<
463 typename iterator_traits<_RandomAccessIterator>::value_type>)
464 __glibcxx_requires_valid_range(__first, __last);
465 __glibcxx_requires_heap(__first, __last);
467 while (__last - __first > 1)
470 std::__pop_heap(__first, __last, __last);
475 * @brief Sort a heap using comparison functor.
476 * @param __first Start of heap.
477 * @param __last End of heap.
478 * @param __comp Comparison functor to use.
479 * @ingroup heap_algorithms
481 * This operation sorts the valid heap in the range [__first,__last).
482 * Comparisons are made using __comp.
484 template<typename _RandomAccessIterator, typename _Compare>
486 sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
489 // concept requirements
490 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
491 _RandomAccessIterator>)
492 __glibcxx_requires_valid_range(__first, __last);
493 __glibcxx_requires_heap_pred(__first, __last, __comp);
495 while (__last - __first > 1)
498 std::__pop_heap(__first, __last, __last, __comp);
502 #ifdef __GXX_EXPERIMENTAL_CXX0X__
504 * @brief Search the end of a heap.
505 * @param __first Start of range.
506 * @param __last End of range.
507 * @return An iterator pointing to the first element not in the heap.
508 * @ingroup heap_algorithms
510 * This operation returns the last iterator i in [__first, __last) for which
511 * the range [__first, i) is a heap.
513 template<typename _RandomAccessIterator>
514 inline _RandomAccessIterator
515 is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last)
517 // concept requirements
518 __glibcxx_function_requires(_RandomAccessIteratorConcept<
519 _RandomAccessIterator>)
520 __glibcxx_function_requires(_LessThanComparableConcept<
521 typename iterator_traits<_RandomAccessIterator>::value_type>)
522 __glibcxx_requires_valid_range(__first, __last);
524 return __first + std::__is_heap_until(__first, std::distance(__first,
529 * @brief Search the end of a heap using comparison functor.
530 * @param __first Start of range.
531 * @param __last End of range.
532 * @param __comp Comparison functor to use.
533 * @return An iterator pointing to the first element not in the heap.
534 * @ingroup heap_algorithms
536 * This operation returns the last iterator i in [__first, __last) for which
537 * the range [__first, i) is a heap. Comparisons are made using __comp.
539 template<typename _RandomAccessIterator, typename _Compare>
540 inline _RandomAccessIterator
541 is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last,
544 // concept requirements
545 __glibcxx_function_requires(_RandomAccessIteratorConcept<
546 _RandomAccessIterator>)
547 __glibcxx_requires_valid_range(__first, __last);
549 return __first + std::__is_heap_until(__first, std::distance(__first,
555 * @brief Determines whether a range is a heap.
556 * @param __first Start of range.
557 * @param __last End of range.
558 * @return True if range is a heap, false otherwise.
559 * @ingroup heap_algorithms
561 template<typename _RandomAccessIterator>
563 is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
564 { return std::is_heap_until(__first, __last) == __last; }
567 * @brief Determines whether a range is a heap using comparison functor.
568 * @param __first Start of range.
569 * @param __last End of range.
570 * @param __comp Comparison functor to use.
571 * @return True if range is a heap, false otherwise.
572 * @ingroup heap_algorithms
574 template<typename _RandomAccessIterator, typename _Compare>
576 is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
578 { return std::is_heap_until(__first, __last, __comp) == __last; }
581 _GLIBCXX_END_NAMESPACE_VERSION
584 #endif /* _STL_HEAP_H */