stl_heap.h (pop_heap): Check for non-empty range in overload taking a predicate.
[gcc.git] / libstdc++-v3 / include / bits / stl_heap.h
1 // Heap implementation -*- C++ -*-
2
3 // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
4 // 2011 Free Software Foundation, Inc.
5 //
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)
10 // any later version.
11
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.
16
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.
20
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/>.
25
26 /*
27 *
28 * Copyright (c) 1994
29 * Hewlett-Packard Company
30 *
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.
38 *
39 * Copyright (c) 1997
40 * Silicon Graphics Computer Systems, Inc.
41 *
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.
49 */
50
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}
54 */
55
56 #ifndef _STL_HEAP_H
57 #define _STL_HEAP_H 1
58
59 #include <debug/debug.h>
60 #include <bits/move.h>
61
62 namespace std _GLIBCXX_VISIBILITY(default)
63 {
64 _GLIBCXX_BEGIN_NAMESPACE_VERSION
65
66 /**
67 * @defgroup heap_algorithms Heap
68 * @ingroup sorting_algorithms
69 */
70
71 template<typename _RandomAccessIterator, typename _Distance>
72 _Distance
73 __is_heap_until(_RandomAccessIterator __first, _Distance __n)
74 {
75 _Distance __parent = 0;
76 for (_Distance __child = 1; __child < __n; ++__child)
77 {
78 if (__first[__parent] < __first[__child])
79 return __child;
80 if ((__child & 1) == 0)
81 ++__parent;
82 }
83 return __n;
84 }
85
86 template<typename _RandomAccessIterator, typename _Distance,
87 typename _Compare>
88 _Distance
89 __is_heap_until(_RandomAccessIterator __first, _Distance __n,
90 _Compare __comp)
91 {
92 _Distance __parent = 0;
93 for (_Distance __child = 1; __child < __n; ++__child)
94 {
95 if (__comp(__first[__parent], __first[__child]))
96 return __child;
97 if ((__child & 1) == 0)
98 ++__parent;
99 }
100 return __n;
101 }
102
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>
106 inline bool
107 __is_heap(_RandomAccessIterator __first, _Distance __n)
108 { return std::__is_heap_until(__first, __n) == __n; }
109
110 template<typename _RandomAccessIterator, typename _Compare,
111 typename _Distance>
112 inline bool
113 __is_heap(_RandomAccessIterator __first, _Compare __comp, _Distance __n)
114 { return std::__is_heap_until(__first, __n, __comp) == __n; }
115
116 template<typename _RandomAccessIterator>
117 inline bool
118 __is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
119 { return std::__is_heap(__first, std::distance(__first, __last)); }
120
121 template<typename _RandomAccessIterator, typename _Compare>
122 inline bool
123 __is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
124 _Compare __comp)
125 { return std::__is_heap(__first, __comp, std::distance(__first, __last)); }
126
127 // Heap-manipulation functions: push_heap, pop_heap, make_heap, sort_heap,
128 // + is_heap and is_heap_until in C++0x.
129
130 template<typename _RandomAccessIterator, typename _Distance, typename _Tp>
131 void
132 __push_heap(_RandomAccessIterator __first,
133 _Distance __holeIndex, _Distance __topIndex, _Tp __value)
134 {
135 _Distance __parent = (__holeIndex - 1) / 2;
136 while (__holeIndex > __topIndex && *(__first + __parent) < __value)
137 {
138 *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __parent));
139 __holeIndex = __parent;
140 __parent = (__holeIndex - 1) / 2;
141 }
142 *(__first + __holeIndex) = _GLIBCXX_MOVE(__value);
143 }
144
145 /**
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
150 *
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.
154 */
155 template<typename _RandomAccessIterator>
156 inline void
157 push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
158 {
159 typedef typename iterator_traits<_RandomAccessIterator>::value_type
160 _ValueType;
161 typedef typename iterator_traits<_RandomAccessIterator>::difference_type
162 _DistanceType;
163
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);
170
171 _ValueType __value = _GLIBCXX_MOVE(*(__last - 1));
172 std::__push_heap(__first, _DistanceType((__last - __first) - 1),
173 _DistanceType(0), _GLIBCXX_MOVE(__value));
174 }
175
176 template<typename _RandomAccessIterator, typename _Distance, typename _Tp,
177 typename _Compare>
178 void
179 __push_heap(_RandomAccessIterator __first, _Distance __holeIndex,
180 _Distance __topIndex, _Tp __value, _Compare __comp)
181 {
182 _Distance __parent = (__holeIndex - 1) / 2;
183 while (__holeIndex > __topIndex
184 && __comp(*(__first + __parent), __value))
185 {
186 *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __parent));
187 __holeIndex = __parent;
188 __parent = (__holeIndex - 1) / 2;
189 }
190 *(__first + __holeIndex) = _GLIBCXX_MOVE(__value);
191 }
192
193 /**
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
199 *
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.
204 */
205 template<typename _RandomAccessIterator, typename _Compare>
206 inline void
207 push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
208 _Compare __comp)
209 {
210 typedef typename iterator_traits<_RandomAccessIterator>::value_type
211 _ValueType;
212 typedef typename iterator_traits<_RandomAccessIterator>::difference_type
213 _DistanceType;
214
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);
220
221 _ValueType __value = _GLIBCXX_MOVE(*(__last - 1));
222 std::__push_heap(__first, _DistanceType((__last - __first) - 1),
223 _DistanceType(0), _GLIBCXX_MOVE(__value), __comp);
224 }
225
226 template<typename _RandomAccessIterator, typename _Distance, typename _Tp>
227 void
228 __adjust_heap(_RandomAccessIterator __first, _Distance __holeIndex,
229 _Distance __len, _Tp __value)
230 {
231 const _Distance __topIndex = __holeIndex;
232 _Distance __secondChild = __holeIndex;
233 while (__secondChild < (__len - 1) / 2)
234 {
235 __secondChild = 2 * (__secondChild + 1);
236 if (*(__first + __secondChild) < *(__first + (__secondChild - 1)))
237 __secondChild--;
238 *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __secondChild));
239 __holeIndex = __secondChild;
240 }
241 if ((__len & 1) == 0 && __secondChild == (__len - 2) / 2)
242 {
243 __secondChild = 2 * (__secondChild + 1);
244 *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first
245 + (__secondChild - 1)));
246 __holeIndex = __secondChild - 1;
247 }
248 std::__push_heap(__first, __holeIndex, __topIndex,
249 _GLIBCXX_MOVE(__value));
250 }
251
252 template<typename _RandomAccessIterator>
253 inline void
254 __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
255 _RandomAccessIterator __result)
256 {
257 typedef typename iterator_traits<_RandomAccessIterator>::value_type
258 _ValueType;
259 typedef typename iterator_traits<_RandomAccessIterator>::difference_type
260 _DistanceType;
261
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));
267 }
268
269 /**
270 * @brief Pop an element off a heap.
271 * @param __first Start of heap.
272 * @param __last End of heap.
273 * @pre [__first, __last) is a valid, non-empty range.
274 * @ingroup heap_algorithms
275 *
276 * This operation pops the top of the heap. The elements __first
277 * and __last-1 are swapped and [__first,__last-1) is made into a
278 * heap.
279 */
280 template<typename _RandomAccessIterator>
281 inline void
282 pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
283 {
284 typedef typename iterator_traits<_RandomAccessIterator>::value_type
285 _ValueType;
286
287 // concept requirements
288 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
289 _RandomAccessIterator>)
290 __glibcxx_function_requires(_LessThanComparableConcept<_ValueType>)
291 __glibcxx_requires_non_empty_range(__first, __last);
292 __glibcxx_requires_valid_range(__first, __last);
293 __glibcxx_requires_heap(__first, __last);
294
295 --__last;
296 std::__pop_heap(__first, __last, __last);
297 }
298
299 template<typename _RandomAccessIterator, typename _Distance,
300 typename _Tp, typename _Compare>
301 void
302 __adjust_heap(_RandomAccessIterator __first, _Distance __holeIndex,
303 _Distance __len, _Tp __value, _Compare __comp)
304 {
305 const _Distance __topIndex = __holeIndex;
306 _Distance __secondChild = __holeIndex;
307 while (__secondChild < (__len - 1) / 2)
308 {
309 __secondChild = 2 * (__secondChild + 1);
310 if (__comp(*(__first + __secondChild),
311 *(__first + (__secondChild - 1))))
312 __secondChild--;
313 *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __secondChild));
314 __holeIndex = __secondChild;
315 }
316 if ((__len & 1) == 0 && __secondChild == (__len - 2) / 2)
317 {
318 __secondChild = 2 * (__secondChild + 1);
319 *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first
320 + (__secondChild - 1)));
321 __holeIndex = __secondChild - 1;
322 }
323 std::__push_heap(__first, __holeIndex, __topIndex,
324 _GLIBCXX_MOVE(__value), __comp);
325 }
326
327 template<typename _RandomAccessIterator, typename _Compare>
328 inline void
329 __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
330 _RandomAccessIterator __result, _Compare __comp)
331 {
332 typedef typename iterator_traits<_RandomAccessIterator>::value_type
333 _ValueType;
334 typedef typename iterator_traits<_RandomAccessIterator>::difference_type
335 _DistanceType;
336
337 _ValueType __value = _GLIBCXX_MOVE(*__result);
338 *__result = _GLIBCXX_MOVE(*__first);
339 std::__adjust_heap(__first, _DistanceType(0),
340 _DistanceType(__last - __first),
341 _GLIBCXX_MOVE(__value), __comp);
342 }
343
344 /**
345 * @brief Pop an element off a heap using comparison functor.
346 * @param __first Start of heap.
347 * @param __last End of heap.
348 * @param __comp Comparison functor to use.
349 * @ingroup heap_algorithms
350 *
351 * This operation pops the top of the heap. The elements __first
352 * and __last-1 are swapped and [__first,__last-1) is made into a
353 * heap. Comparisons are made using comp.
354 */
355 template<typename _RandomAccessIterator, typename _Compare>
356 inline void
357 pop_heap(_RandomAccessIterator __first,
358 _RandomAccessIterator __last, _Compare __comp)
359 {
360 // concept requirements
361 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
362 _RandomAccessIterator>)
363 __glibcxx_requires_valid_range(__first, __last);
364 __glibcxx_requires_non_empty_range(__first, __last);
365 __glibcxx_requires_heap_pred(__first, __last, __comp);
366
367 --__last;
368 std::__pop_heap(__first, __last, __last, __comp);
369 }
370
371 /**
372 * @brief Construct a heap over a range.
373 * @param __first Start of heap.
374 * @param __last End of heap.
375 * @ingroup heap_algorithms
376 *
377 * This operation makes the elements in [__first,__last) into a heap.
378 */
379 template<typename _RandomAccessIterator>
380 void
381 make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
382 {
383 typedef typename iterator_traits<_RandomAccessIterator>::value_type
384 _ValueType;
385 typedef typename iterator_traits<_RandomAccessIterator>::difference_type
386 _DistanceType;
387
388 // concept requirements
389 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
390 _RandomAccessIterator>)
391 __glibcxx_function_requires(_LessThanComparableConcept<_ValueType>)
392 __glibcxx_requires_valid_range(__first, __last);
393
394 if (__last - __first < 2)
395 return;
396
397 const _DistanceType __len = __last - __first;
398 _DistanceType __parent = (__len - 2) / 2;
399 while (true)
400 {
401 _ValueType __value = _GLIBCXX_MOVE(*(__first + __parent));
402 std::__adjust_heap(__first, __parent, __len, _GLIBCXX_MOVE(__value));
403 if (__parent == 0)
404 return;
405 __parent--;
406 }
407 }
408
409 /**
410 * @brief Construct a heap over a range using comparison functor.
411 * @param __first Start of heap.
412 * @param __last End of heap.
413 * @param __comp Comparison functor to use.
414 * @ingroup heap_algorithms
415 *
416 * This operation makes the elements in [__first,__last) into a heap.
417 * Comparisons are made using __comp.
418 */
419 template<typename _RandomAccessIterator, typename _Compare>
420 void
421 make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
422 _Compare __comp)
423 {
424 typedef typename iterator_traits<_RandomAccessIterator>::value_type
425 _ValueType;
426 typedef typename iterator_traits<_RandomAccessIterator>::difference_type
427 _DistanceType;
428
429 // concept requirements
430 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
431 _RandomAccessIterator>)
432 __glibcxx_requires_valid_range(__first, __last);
433
434 if (__last - __first < 2)
435 return;
436
437 const _DistanceType __len = __last - __first;
438 _DistanceType __parent = (__len - 2) / 2;
439 while (true)
440 {
441 _ValueType __value = _GLIBCXX_MOVE(*(__first + __parent));
442 std::__adjust_heap(__first, __parent, __len, _GLIBCXX_MOVE(__value),
443 __comp);
444 if (__parent == 0)
445 return;
446 __parent--;
447 }
448 }
449
450 /**
451 * @brief Sort a heap.
452 * @param __first Start of heap.
453 * @param __last End of heap.
454 * @ingroup heap_algorithms
455 *
456 * This operation sorts the valid heap in the range [__first,__last).
457 */
458 template<typename _RandomAccessIterator>
459 void
460 sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
461 {
462 // concept requirements
463 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
464 _RandomAccessIterator>)
465 __glibcxx_function_requires(_LessThanComparableConcept<
466 typename iterator_traits<_RandomAccessIterator>::value_type>)
467 __glibcxx_requires_valid_range(__first, __last);
468 __glibcxx_requires_heap(__first, __last);
469
470 while (__last - __first > 1)
471 {
472 --__last;
473 std::__pop_heap(__first, __last, __last);
474 }
475 }
476
477 /**
478 * @brief Sort a heap using comparison functor.
479 * @param __first Start of heap.
480 * @param __last End of heap.
481 * @param __comp Comparison functor to use.
482 * @ingroup heap_algorithms
483 *
484 * This operation sorts the valid heap in the range [__first,__last).
485 * Comparisons are made using __comp.
486 */
487 template<typename _RandomAccessIterator, typename _Compare>
488 void
489 sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
490 _Compare __comp)
491 {
492 // concept requirements
493 __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
494 _RandomAccessIterator>)
495 __glibcxx_requires_valid_range(__first, __last);
496 __glibcxx_requires_heap_pred(__first, __last, __comp);
497
498 while (__last - __first > 1)
499 {
500 --__last;
501 std::__pop_heap(__first, __last, __last, __comp);
502 }
503 }
504
505 #ifdef __GXX_EXPERIMENTAL_CXX0X__
506 /**
507 * @brief Search the end of a heap.
508 * @param __first Start of range.
509 * @param __last End of range.
510 * @return An iterator pointing to the first element not in the heap.
511 * @ingroup heap_algorithms
512 *
513 * This operation returns the last iterator i in [__first, __last) for which
514 * the range [__first, i) is a heap.
515 */
516 template<typename _RandomAccessIterator>
517 inline _RandomAccessIterator
518 is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last)
519 {
520 // concept requirements
521 __glibcxx_function_requires(_RandomAccessIteratorConcept<
522 _RandomAccessIterator>)
523 __glibcxx_function_requires(_LessThanComparableConcept<
524 typename iterator_traits<_RandomAccessIterator>::value_type>)
525 __glibcxx_requires_valid_range(__first, __last);
526
527 return __first + std::__is_heap_until(__first, std::distance(__first,
528 __last));
529 }
530
531 /**
532 * @brief Search the end of a heap using comparison functor.
533 * @param __first Start of range.
534 * @param __last End of range.
535 * @param __comp Comparison functor to use.
536 * @return An iterator pointing to the first element not in the heap.
537 * @ingroup heap_algorithms
538 *
539 * This operation returns the last iterator i in [__first, __last) for which
540 * the range [__first, i) is a heap. Comparisons are made using __comp.
541 */
542 template<typename _RandomAccessIterator, typename _Compare>
543 inline _RandomAccessIterator
544 is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last,
545 _Compare __comp)
546 {
547 // concept requirements
548 __glibcxx_function_requires(_RandomAccessIteratorConcept<
549 _RandomAccessIterator>)
550 __glibcxx_requires_valid_range(__first, __last);
551
552 return __first + std::__is_heap_until(__first, std::distance(__first,
553 __last),
554 __comp);
555 }
556
557 /**
558 * @brief Determines whether a range is a heap.
559 * @param __first Start of range.
560 * @param __last End of range.
561 * @return True if range is a heap, false otherwise.
562 * @ingroup heap_algorithms
563 */
564 template<typename _RandomAccessIterator>
565 inline bool
566 is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
567 { return std::is_heap_until(__first, __last) == __last; }
568
569 /**
570 * @brief Determines whether a range is a heap using comparison functor.
571 * @param __first Start of range.
572 * @param __last End of range.
573 * @param __comp Comparison functor to use.
574 * @return True if range is a heap, false otherwise.
575 * @ingroup heap_algorithms
576 */
577 template<typename _RandomAccessIterator, typename _Compare>
578 inline bool
579 is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
580 _Compare __comp)
581 { return std::is_heap_until(__first, __last, __comp) == __last; }
582 #endif
583
584 _GLIBCXX_END_NAMESPACE_VERSION
585 } // namespace
586
587 #endif /* _STL_HEAP_H */