1*38fd1498Szrj // Heap implementation -*- C++ -*-
2*38fd1498Szrj
3*38fd1498Szrj // Copyright (C) 2001-2018 Free Software Foundation, Inc.
4*38fd1498Szrj //
5*38fd1498Szrj // This file is part of the GNU ISO C++ Library. This library is free
6*38fd1498Szrj // software; you can redistribute it and/or modify it under the
7*38fd1498Szrj // terms of the GNU General Public License as published by the
8*38fd1498Szrj // Free Software Foundation; either version 3, or (at your option)
9*38fd1498Szrj // any later version.
10*38fd1498Szrj
11*38fd1498Szrj // This library is distributed in the hope that it will be useful,
12*38fd1498Szrj // but WITHOUT ANY WARRANTY; without even the implied warranty of
13*38fd1498Szrj // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14*38fd1498Szrj // GNU General Public License for more details.
15*38fd1498Szrj
16*38fd1498Szrj // Under Section 7 of GPL version 3, you are granted additional
17*38fd1498Szrj // permissions described in the GCC Runtime Library Exception, version
18*38fd1498Szrj // 3.1, as published by the Free Software Foundation.
19*38fd1498Szrj
20*38fd1498Szrj // You should have received a copy of the GNU General Public License and
21*38fd1498Szrj // a copy of the GCC Runtime Library Exception along with this program;
22*38fd1498Szrj // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23*38fd1498Szrj // <http://www.gnu.org/licenses/>.
24*38fd1498Szrj
25*38fd1498Szrj /*
26*38fd1498Szrj *
27*38fd1498Szrj * Copyright (c) 1994
28*38fd1498Szrj * Hewlett-Packard Company
29*38fd1498Szrj *
30*38fd1498Szrj * Permission to use, copy, modify, distribute and sell this software
31*38fd1498Szrj * and its documentation for any purpose is hereby granted without fee,
32*38fd1498Szrj * provided that the above copyright notice appear in all copies and
33*38fd1498Szrj * that both that copyright notice and this permission notice appear
34*38fd1498Szrj * in supporting documentation. Hewlett-Packard Company makes no
35*38fd1498Szrj * representations about the suitability of this software for any
36*38fd1498Szrj * purpose. It is provided "as is" without express or implied warranty.
37*38fd1498Szrj *
38*38fd1498Szrj * Copyright (c) 1997
39*38fd1498Szrj * Silicon Graphics Computer Systems, Inc.
40*38fd1498Szrj *
41*38fd1498Szrj * Permission to use, copy, modify, distribute and sell this software
42*38fd1498Szrj * and its documentation for any purpose is hereby granted without fee,
43*38fd1498Szrj * provided that the above copyright notice appear in all copies and
44*38fd1498Szrj * that both that copyright notice and this permission notice appear
45*38fd1498Szrj * in supporting documentation. Silicon Graphics makes no
46*38fd1498Szrj * representations about the suitability of this software for any
47*38fd1498Szrj * purpose. It is provided "as is" without express or implied warranty.
48*38fd1498Szrj */
49*38fd1498Szrj
50*38fd1498Szrj /** @file bits/stl_heap.h
51*38fd1498Szrj * This is an internal header file, included by other library headers.
52*38fd1498Szrj * Do not attempt to use it directly. @headername{queue}
53*38fd1498Szrj */
54*38fd1498Szrj
55*38fd1498Szrj #ifndef _STL_HEAP_H
56*38fd1498Szrj #define _STL_HEAP_H 1
57*38fd1498Szrj
58*38fd1498Szrj #include <debug/debug.h>
59*38fd1498Szrj #include <bits/move.h>
60*38fd1498Szrj #include <bits/predefined_ops.h>
61*38fd1498Szrj
_GLIBCXX_VISIBILITY(default)62*38fd1498Szrj namespace std _GLIBCXX_VISIBILITY(default)
63*38fd1498Szrj {
64*38fd1498Szrj _GLIBCXX_BEGIN_NAMESPACE_VERSION
65*38fd1498Szrj
66*38fd1498Szrj /**
67*38fd1498Szrj * @defgroup heap_algorithms Heap
68*38fd1498Szrj * @ingroup sorting_algorithms
69*38fd1498Szrj */
70*38fd1498Szrj
71*38fd1498Szrj template<typename _RandomAccessIterator, typename _Distance,
72*38fd1498Szrj typename _Compare>
73*38fd1498Szrj _Distance
74*38fd1498Szrj __is_heap_until(_RandomAccessIterator __first, _Distance __n,
75*38fd1498Szrj _Compare& __comp)
76*38fd1498Szrj {
77*38fd1498Szrj _Distance __parent = 0;
78*38fd1498Szrj for (_Distance __child = 1; __child < __n; ++__child)
79*38fd1498Szrj {
80*38fd1498Szrj if (__comp(__first + __parent, __first + __child))
81*38fd1498Szrj return __child;
82*38fd1498Szrj if ((__child & 1) == 0)
83*38fd1498Szrj ++__parent;
84*38fd1498Szrj }
85*38fd1498Szrj return __n;
86*38fd1498Szrj }
87*38fd1498Szrj
88*38fd1498Szrj // __is_heap, a predicate testing whether or not a range is a heap.
89*38fd1498Szrj // This function is an extension, not part of the C++ standard.
90*38fd1498Szrj template<typename _RandomAccessIterator, typename _Distance>
91*38fd1498Szrj inline bool
92*38fd1498Szrj __is_heap(_RandomAccessIterator __first, _Distance __n)
93*38fd1498Szrj {
94*38fd1498Szrj __gnu_cxx::__ops::_Iter_less_iter __comp;
95*38fd1498Szrj return std::__is_heap_until(__first, __n, __comp) == __n;
96*38fd1498Szrj }
97*38fd1498Szrj
98*38fd1498Szrj template<typename _RandomAccessIterator, typename _Compare,
99*38fd1498Szrj typename _Distance>
100*38fd1498Szrj inline bool
101*38fd1498Szrj __is_heap(_RandomAccessIterator __first, _Compare __comp, _Distance __n)
102*38fd1498Szrj {
103*38fd1498Szrj typedef __decltype(__comp) _Cmp;
104*38fd1498Szrj __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp));
105*38fd1498Szrj return std::__is_heap_until(__first, __n, __cmp) == __n;
106*38fd1498Szrj }
107*38fd1498Szrj
108*38fd1498Szrj template<typename _RandomAccessIterator>
109*38fd1498Szrj inline bool
110*38fd1498Szrj __is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
111*38fd1498Szrj { return std::__is_heap(__first, std::distance(__first, __last)); }
112*38fd1498Szrj
113*38fd1498Szrj template<typename _RandomAccessIterator, typename _Compare>
114*38fd1498Szrj inline bool
115*38fd1498Szrj __is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
116*38fd1498Szrj _Compare __comp)
117*38fd1498Szrj {
118*38fd1498Szrj return std::__is_heap(__first, _GLIBCXX_MOVE(__comp),
119*38fd1498Szrj std::distance(__first, __last));
120*38fd1498Szrj }
121*38fd1498Szrj
122*38fd1498Szrj // Heap-manipulation functions: push_heap, pop_heap, make_heap, sort_heap,
123*38fd1498Szrj // + is_heap and is_heap_until in C++0x.
124*38fd1498Szrj
125*38fd1498Szrj template<typename _RandomAccessIterator, typename _Distance, typename _Tp,
126*38fd1498Szrj typename _Compare>
127*38fd1498Szrj void
128*38fd1498Szrj __push_heap(_RandomAccessIterator __first,
129*38fd1498Szrj _Distance __holeIndex, _Distance __topIndex, _Tp __value,
130*38fd1498Szrj _Compare& __comp)
131*38fd1498Szrj {
132*38fd1498Szrj _Distance __parent = (__holeIndex - 1) / 2;
133*38fd1498Szrj while (__holeIndex > __topIndex && __comp(__first + __parent, __value))
134*38fd1498Szrj {
135*38fd1498Szrj *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __parent));
136*38fd1498Szrj __holeIndex = __parent;
137*38fd1498Szrj __parent = (__holeIndex - 1) / 2;
138*38fd1498Szrj }
139*38fd1498Szrj *(__first + __holeIndex) = _GLIBCXX_MOVE(__value);
140*38fd1498Szrj }
141*38fd1498Szrj
142*38fd1498Szrj /**
143*38fd1498Szrj * @brief Push an element onto a heap.
144*38fd1498Szrj * @param __first Start of heap.
145*38fd1498Szrj * @param __last End of heap + element.
146*38fd1498Szrj * @ingroup heap_algorithms
147*38fd1498Szrj *
148*38fd1498Szrj * This operation pushes the element at last-1 onto the valid heap
149*38fd1498Szrj * over the range [__first,__last-1). After completion,
150*38fd1498Szrj * [__first,__last) is a valid heap.
151*38fd1498Szrj */
152*38fd1498Szrj template<typename _RandomAccessIterator>
153*38fd1498Szrj inline void
154*38fd1498Szrj push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
155*38fd1498Szrj {
156*38fd1498Szrj typedef typename iterator_traits<_RandomAccessIterator>::value_type
157*38fd1498Szrj _ValueType;
158*38fd1498Szrj typedef typename iterator_traits<_RandomAccessIterator>::difference_type
159*38fd1498Szrj _DistanceType;
160*38fd1498Szrj
161*38fd1498Szrj // concept requirements
162*38fd1498Szrj __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
163*38fd1498Szrj _RandomAccessIterator>)
164*38fd1498Szrj __glibcxx_function_requires(_LessThanComparableConcept<_ValueType>)
165*38fd1498Szrj __glibcxx_requires_valid_range(__first, __last);
166*38fd1498Szrj __glibcxx_requires_irreflexive(__first, __last);
167*38fd1498Szrj __glibcxx_requires_heap(__first, __last - 1);
168*38fd1498Szrj
169*38fd1498Szrj __gnu_cxx::__ops::_Iter_less_val __comp;
170*38fd1498Szrj _ValueType __value = _GLIBCXX_MOVE(*(__last - 1));
171*38fd1498Szrj std::__push_heap(__first, _DistanceType((__last - __first) - 1),
172*38fd1498Szrj _DistanceType(0), _GLIBCXX_MOVE(__value), __comp);
173*38fd1498Szrj }
174*38fd1498Szrj
175*38fd1498Szrj /**
176*38fd1498Szrj * @brief Push an element onto a heap using comparison functor.
177*38fd1498Szrj * @param __first Start of heap.
178*38fd1498Szrj * @param __last End of heap + element.
179*38fd1498Szrj * @param __comp Comparison functor.
180*38fd1498Szrj * @ingroup heap_algorithms
181*38fd1498Szrj *
182*38fd1498Szrj * This operation pushes the element at __last-1 onto the valid
183*38fd1498Szrj * heap over the range [__first,__last-1). After completion,
184*38fd1498Szrj * [__first,__last) is a valid heap. Compare operations are
185*38fd1498Szrj * performed using comp.
186*38fd1498Szrj */
187*38fd1498Szrj template<typename _RandomAccessIterator, typename _Compare>
188*38fd1498Szrj inline void
189*38fd1498Szrj push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
190*38fd1498Szrj _Compare __comp)
191*38fd1498Szrj {
192*38fd1498Szrj typedef typename iterator_traits<_RandomAccessIterator>::value_type
193*38fd1498Szrj _ValueType;
194*38fd1498Szrj typedef typename iterator_traits<_RandomAccessIterator>::difference_type
195*38fd1498Szrj _DistanceType;
196*38fd1498Szrj
197*38fd1498Szrj // concept requirements
198*38fd1498Szrj __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
199*38fd1498Szrj _RandomAccessIterator>)
200*38fd1498Szrj __glibcxx_requires_valid_range(__first, __last);
201*38fd1498Szrj __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
202*38fd1498Szrj __glibcxx_requires_heap_pred(__first, __last - 1, __comp);
203*38fd1498Szrj
204*38fd1498Szrj __decltype(__gnu_cxx::__ops::__iter_comp_val(_GLIBCXX_MOVE(__comp)))
205*38fd1498Szrj __cmp(_GLIBCXX_MOVE(__comp));
206*38fd1498Szrj _ValueType __value = _GLIBCXX_MOVE(*(__last - 1));
207*38fd1498Szrj std::__push_heap(__first, _DistanceType((__last - __first) - 1),
208*38fd1498Szrj _DistanceType(0), _GLIBCXX_MOVE(__value), __cmp);
209*38fd1498Szrj }
210*38fd1498Szrj
211*38fd1498Szrj template<typename _RandomAccessIterator, typename _Distance,
212*38fd1498Szrj typename _Tp, typename _Compare>
213*38fd1498Szrj void
214*38fd1498Szrj __adjust_heap(_RandomAccessIterator __first, _Distance __holeIndex,
215*38fd1498Szrj _Distance __len, _Tp __value, _Compare __comp)
216*38fd1498Szrj {
217*38fd1498Szrj const _Distance __topIndex = __holeIndex;
218*38fd1498Szrj _Distance __secondChild = __holeIndex;
219*38fd1498Szrj while (__secondChild < (__len - 1) / 2)
220*38fd1498Szrj {
221*38fd1498Szrj __secondChild = 2 * (__secondChild + 1);
222*38fd1498Szrj if (__comp(__first + __secondChild,
223*38fd1498Szrj __first + (__secondChild - 1)))
224*38fd1498Szrj __secondChild--;
225*38fd1498Szrj *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __secondChild));
226*38fd1498Szrj __holeIndex = __secondChild;
227*38fd1498Szrj }
228*38fd1498Szrj if ((__len & 1) == 0 && __secondChild == (__len - 2) / 2)
229*38fd1498Szrj {
230*38fd1498Szrj __secondChild = 2 * (__secondChild + 1);
231*38fd1498Szrj *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first
232*38fd1498Szrj + (__secondChild - 1)));
233*38fd1498Szrj __holeIndex = __secondChild - 1;
234*38fd1498Szrj }
235*38fd1498Szrj __decltype(__gnu_cxx::__ops::__iter_comp_val(_GLIBCXX_MOVE(__comp)))
236*38fd1498Szrj __cmp(_GLIBCXX_MOVE(__comp));
237*38fd1498Szrj std::__push_heap(__first, __holeIndex, __topIndex,
238*38fd1498Szrj _GLIBCXX_MOVE(__value), __cmp);
239*38fd1498Szrj }
240*38fd1498Szrj
241*38fd1498Szrj template<typename _RandomAccessIterator, typename _Compare>
242*38fd1498Szrj inline void
243*38fd1498Szrj __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
244*38fd1498Szrj _RandomAccessIterator __result, _Compare& __comp)
245*38fd1498Szrj {
246*38fd1498Szrj typedef typename iterator_traits<_RandomAccessIterator>::value_type
247*38fd1498Szrj _ValueType;
248*38fd1498Szrj typedef typename iterator_traits<_RandomAccessIterator>::difference_type
249*38fd1498Szrj _DistanceType;
250*38fd1498Szrj
251*38fd1498Szrj _ValueType __value = _GLIBCXX_MOVE(*__result);
252*38fd1498Szrj *__result = _GLIBCXX_MOVE(*__first);
253*38fd1498Szrj std::__adjust_heap(__first, _DistanceType(0),
254*38fd1498Szrj _DistanceType(__last - __first),
255*38fd1498Szrj _GLIBCXX_MOVE(__value), __comp);
256*38fd1498Szrj }
257*38fd1498Szrj
258*38fd1498Szrj /**
259*38fd1498Szrj * @brief Pop an element off a heap.
260*38fd1498Szrj * @param __first Start of heap.
261*38fd1498Szrj * @param __last End of heap.
262*38fd1498Szrj * @pre [__first, __last) is a valid, non-empty range.
263*38fd1498Szrj * @ingroup heap_algorithms
264*38fd1498Szrj *
265*38fd1498Szrj * This operation pops the top of the heap. The elements __first
266*38fd1498Szrj * and __last-1 are swapped and [__first,__last-1) is made into a
267*38fd1498Szrj * heap.
268*38fd1498Szrj */
269*38fd1498Szrj template<typename _RandomAccessIterator>
270*38fd1498Szrj inline void
271*38fd1498Szrj pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
272*38fd1498Szrj {
273*38fd1498Szrj // concept requirements
274*38fd1498Szrj __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
275*38fd1498Szrj _RandomAccessIterator>)
276*38fd1498Szrj __glibcxx_function_requires(_LessThanComparableConcept<
277*38fd1498Szrj typename iterator_traits<_RandomAccessIterator>::value_type>)
278*38fd1498Szrj __glibcxx_requires_non_empty_range(__first, __last);
279*38fd1498Szrj __glibcxx_requires_valid_range(__first, __last);
280*38fd1498Szrj __glibcxx_requires_irreflexive(__first, __last);
281*38fd1498Szrj __glibcxx_requires_heap(__first, __last);
282*38fd1498Szrj
283*38fd1498Szrj if (__last - __first > 1)
284*38fd1498Szrj {
285*38fd1498Szrj --__last;
286*38fd1498Szrj __gnu_cxx::__ops::_Iter_less_iter __comp;
287*38fd1498Szrj std::__pop_heap(__first, __last, __last, __comp);
288*38fd1498Szrj }
289*38fd1498Szrj }
290*38fd1498Szrj
291*38fd1498Szrj /**
292*38fd1498Szrj * @brief Pop an element off a heap using comparison functor.
293*38fd1498Szrj * @param __first Start of heap.
294*38fd1498Szrj * @param __last End of heap.
295*38fd1498Szrj * @param __comp Comparison functor to use.
296*38fd1498Szrj * @ingroup heap_algorithms
297*38fd1498Szrj *
298*38fd1498Szrj * This operation pops the top of the heap. The elements __first
299*38fd1498Szrj * and __last-1 are swapped and [__first,__last-1) is made into a
300*38fd1498Szrj * heap. Comparisons are made using comp.
301*38fd1498Szrj */
302*38fd1498Szrj template<typename _RandomAccessIterator, typename _Compare>
303*38fd1498Szrj inline void
304*38fd1498Szrj pop_heap(_RandomAccessIterator __first,
305*38fd1498Szrj _RandomAccessIterator __last, _Compare __comp)
306*38fd1498Szrj {
307*38fd1498Szrj // concept requirements
308*38fd1498Szrj __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
309*38fd1498Szrj _RandomAccessIterator>)
310*38fd1498Szrj __glibcxx_requires_valid_range(__first, __last);
311*38fd1498Szrj __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
312*38fd1498Szrj __glibcxx_requires_non_empty_range(__first, __last);
313*38fd1498Szrj __glibcxx_requires_heap_pred(__first, __last, __comp);
314*38fd1498Szrj
315*38fd1498Szrj if (__last - __first > 1)
316*38fd1498Szrj {
317*38fd1498Szrj typedef __decltype(__comp) _Cmp;
318*38fd1498Szrj __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp));
319*38fd1498Szrj --__last;
320*38fd1498Szrj std::__pop_heap(__first, __last, __last, __cmp);
321*38fd1498Szrj }
322*38fd1498Szrj }
323*38fd1498Szrj
324*38fd1498Szrj template<typename _RandomAccessIterator, typename _Compare>
325*38fd1498Szrj void
326*38fd1498Szrj __make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
327*38fd1498Szrj _Compare& __comp)
328*38fd1498Szrj {
329*38fd1498Szrj typedef typename iterator_traits<_RandomAccessIterator>::value_type
330*38fd1498Szrj _ValueType;
331*38fd1498Szrj typedef typename iterator_traits<_RandomAccessIterator>::difference_type
332*38fd1498Szrj _DistanceType;
333*38fd1498Szrj
334*38fd1498Szrj if (__last - __first < 2)
335*38fd1498Szrj return;
336*38fd1498Szrj
337*38fd1498Szrj const _DistanceType __len = __last - __first;
338*38fd1498Szrj _DistanceType __parent = (__len - 2) / 2;
339*38fd1498Szrj while (true)
340*38fd1498Szrj {
341*38fd1498Szrj _ValueType __value = _GLIBCXX_MOVE(*(__first + __parent));
342*38fd1498Szrj std::__adjust_heap(__first, __parent, __len, _GLIBCXX_MOVE(__value),
343*38fd1498Szrj __comp);
344*38fd1498Szrj if (__parent == 0)
345*38fd1498Szrj return;
346*38fd1498Szrj __parent--;
347*38fd1498Szrj }
348*38fd1498Szrj }
349*38fd1498Szrj
350*38fd1498Szrj /**
351*38fd1498Szrj * @brief Construct a heap over a range.
352*38fd1498Szrj * @param __first Start of heap.
353*38fd1498Szrj * @param __last End of heap.
354*38fd1498Szrj * @ingroup heap_algorithms
355*38fd1498Szrj *
356*38fd1498Szrj * This operation makes the elements in [__first,__last) into a heap.
357*38fd1498Szrj */
358*38fd1498Szrj template<typename _RandomAccessIterator>
359*38fd1498Szrj inline void
360*38fd1498Szrj make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
361*38fd1498Szrj {
362*38fd1498Szrj // concept requirements
363*38fd1498Szrj __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
364*38fd1498Szrj _RandomAccessIterator>)
365*38fd1498Szrj __glibcxx_function_requires(_LessThanComparableConcept<
366*38fd1498Szrj typename iterator_traits<_RandomAccessIterator>::value_type>)
367*38fd1498Szrj __glibcxx_requires_valid_range(__first, __last);
368*38fd1498Szrj __glibcxx_requires_irreflexive(__first, __last);
369*38fd1498Szrj
370*38fd1498Szrj __gnu_cxx::__ops::_Iter_less_iter __comp;
371*38fd1498Szrj std::__make_heap(__first, __last, __comp);
372*38fd1498Szrj }
373*38fd1498Szrj
374*38fd1498Szrj /**
375*38fd1498Szrj * @brief Construct a heap over a range using comparison functor.
376*38fd1498Szrj * @param __first Start of heap.
377*38fd1498Szrj * @param __last End of heap.
378*38fd1498Szrj * @param __comp Comparison functor to use.
379*38fd1498Szrj * @ingroup heap_algorithms
380*38fd1498Szrj *
381*38fd1498Szrj * This operation makes the elements in [__first,__last) into a heap.
382*38fd1498Szrj * Comparisons are made using __comp.
383*38fd1498Szrj */
384*38fd1498Szrj template<typename _RandomAccessIterator, typename _Compare>
385*38fd1498Szrj inline void
386*38fd1498Szrj make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
387*38fd1498Szrj _Compare __comp)
388*38fd1498Szrj {
389*38fd1498Szrj // concept requirements
390*38fd1498Szrj __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
391*38fd1498Szrj _RandomAccessIterator>)
392*38fd1498Szrj __glibcxx_requires_valid_range(__first, __last);
393*38fd1498Szrj __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
394*38fd1498Szrj
395*38fd1498Szrj typedef __decltype(__comp) _Cmp;
396*38fd1498Szrj __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp));
397*38fd1498Szrj std::__make_heap(__first, __last, __cmp);
398*38fd1498Szrj }
399*38fd1498Szrj
400*38fd1498Szrj template<typename _RandomAccessIterator, typename _Compare>
401*38fd1498Szrj void
402*38fd1498Szrj __sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
403*38fd1498Szrj _Compare& __comp)
404*38fd1498Szrj {
405*38fd1498Szrj while (__last - __first > 1)
406*38fd1498Szrj {
407*38fd1498Szrj --__last;
408*38fd1498Szrj std::__pop_heap(__first, __last, __last, __comp);
409*38fd1498Szrj }
410*38fd1498Szrj }
411*38fd1498Szrj
412*38fd1498Szrj /**
413*38fd1498Szrj * @brief Sort a heap.
414*38fd1498Szrj * @param __first Start of heap.
415*38fd1498Szrj * @param __last End of heap.
416*38fd1498Szrj * @ingroup heap_algorithms
417*38fd1498Szrj *
418*38fd1498Szrj * This operation sorts the valid heap in the range [__first,__last).
419*38fd1498Szrj */
420*38fd1498Szrj template<typename _RandomAccessIterator>
421*38fd1498Szrj inline void
422*38fd1498Szrj sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
423*38fd1498Szrj {
424*38fd1498Szrj // concept requirements
425*38fd1498Szrj __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
426*38fd1498Szrj _RandomAccessIterator>)
427*38fd1498Szrj __glibcxx_function_requires(_LessThanComparableConcept<
428*38fd1498Szrj typename iterator_traits<_RandomAccessIterator>::value_type>)
429*38fd1498Szrj __glibcxx_requires_valid_range(__first, __last);
430*38fd1498Szrj __glibcxx_requires_irreflexive(__first, __last);
431*38fd1498Szrj __glibcxx_requires_heap(__first, __last);
432*38fd1498Szrj
433*38fd1498Szrj __gnu_cxx::__ops::_Iter_less_iter __comp;
434*38fd1498Szrj std::__sort_heap(__first, __last, __comp);
435*38fd1498Szrj }
436*38fd1498Szrj
437*38fd1498Szrj /**
438*38fd1498Szrj * @brief Sort a heap using comparison functor.
439*38fd1498Szrj * @param __first Start of heap.
440*38fd1498Szrj * @param __last End of heap.
441*38fd1498Szrj * @param __comp Comparison functor to use.
442*38fd1498Szrj * @ingroup heap_algorithms
443*38fd1498Szrj *
444*38fd1498Szrj * This operation sorts the valid heap in the range [__first,__last).
445*38fd1498Szrj * Comparisons are made using __comp.
446*38fd1498Szrj */
447*38fd1498Szrj template<typename _RandomAccessIterator, typename _Compare>
448*38fd1498Szrj inline void
449*38fd1498Szrj sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
450*38fd1498Szrj _Compare __comp)
451*38fd1498Szrj {
452*38fd1498Szrj // concept requirements
453*38fd1498Szrj __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
454*38fd1498Szrj _RandomAccessIterator>)
455*38fd1498Szrj __glibcxx_requires_valid_range(__first, __last);
456*38fd1498Szrj __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
457*38fd1498Szrj __glibcxx_requires_heap_pred(__first, __last, __comp);
458*38fd1498Szrj
459*38fd1498Szrj typedef __decltype(__comp) _Cmp;
460*38fd1498Szrj __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp));
461*38fd1498Szrj std::__sort_heap(__first, __last, __cmp);
462*38fd1498Szrj }
463*38fd1498Szrj
464*38fd1498Szrj #if __cplusplus >= 201103L
465*38fd1498Szrj /**
466*38fd1498Szrj * @brief Search the end of a heap.
467*38fd1498Szrj * @param __first Start of range.
468*38fd1498Szrj * @param __last End of range.
469*38fd1498Szrj * @return An iterator pointing to the first element not in the heap.
470*38fd1498Szrj * @ingroup heap_algorithms
471*38fd1498Szrj *
472*38fd1498Szrj * This operation returns the last iterator i in [__first, __last) for which
473*38fd1498Szrj * the range [__first, i) is a heap.
474*38fd1498Szrj */
475*38fd1498Szrj template<typename _RandomAccessIterator>
476*38fd1498Szrj inline _RandomAccessIterator
477*38fd1498Szrj is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last)
478*38fd1498Szrj {
479*38fd1498Szrj // concept requirements
480*38fd1498Szrj __glibcxx_function_requires(_RandomAccessIteratorConcept<
481*38fd1498Szrj _RandomAccessIterator>)
482*38fd1498Szrj __glibcxx_function_requires(_LessThanComparableConcept<
483*38fd1498Szrj typename iterator_traits<_RandomAccessIterator>::value_type>)
484*38fd1498Szrj __glibcxx_requires_valid_range(__first, __last);
485*38fd1498Szrj __glibcxx_requires_irreflexive(__first, __last);
486*38fd1498Szrj
487*38fd1498Szrj __gnu_cxx::__ops::_Iter_less_iter __comp;
488*38fd1498Szrj return __first +
489*38fd1498Szrj std::__is_heap_until(__first, std::distance(__first, __last), __comp);
490*38fd1498Szrj }
491*38fd1498Szrj
492*38fd1498Szrj /**
493*38fd1498Szrj * @brief Search the end of a heap using comparison functor.
494*38fd1498Szrj * @param __first Start of range.
495*38fd1498Szrj * @param __last End of range.
496*38fd1498Szrj * @param __comp Comparison functor to use.
497*38fd1498Szrj * @return An iterator pointing to the first element not in the heap.
498*38fd1498Szrj * @ingroup heap_algorithms
499*38fd1498Szrj *
500*38fd1498Szrj * This operation returns the last iterator i in [__first, __last) for which
501*38fd1498Szrj * the range [__first, i) is a heap. Comparisons are made using __comp.
502*38fd1498Szrj */
503*38fd1498Szrj template<typename _RandomAccessIterator, typename _Compare>
504*38fd1498Szrj inline _RandomAccessIterator
505*38fd1498Szrj is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last,
506*38fd1498Szrj _Compare __comp)
507*38fd1498Szrj {
508*38fd1498Szrj // concept requirements
509*38fd1498Szrj __glibcxx_function_requires(_RandomAccessIteratorConcept<
510*38fd1498Szrj _RandomAccessIterator>)
511*38fd1498Szrj __glibcxx_requires_valid_range(__first, __last);
512*38fd1498Szrj __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
513*38fd1498Szrj
514*38fd1498Szrj typedef __decltype(__comp) _Cmp;
515*38fd1498Szrj __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp));
516*38fd1498Szrj return __first
517*38fd1498Szrj + std::__is_heap_until(__first, std::distance(__first, __last), __cmp);
518*38fd1498Szrj }
519*38fd1498Szrj
520*38fd1498Szrj /**
521*38fd1498Szrj * @brief Determines whether a range is a heap.
522*38fd1498Szrj * @param __first Start of range.
523*38fd1498Szrj * @param __last End of range.
524*38fd1498Szrj * @return True if range is a heap, false otherwise.
525*38fd1498Szrj * @ingroup heap_algorithms
526*38fd1498Szrj */
527*38fd1498Szrj template<typename _RandomAccessIterator>
528*38fd1498Szrj inline bool
529*38fd1498Szrj is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
530*38fd1498Szrj { return std::is_heap_until(__first, __last) == __last; }
531*38fd1498Szrj
532*38fd1498Szrj /**
533*38fd1498Szrj * @brief Determines whether a range is a heap using comparison functor.
534*38fd1498Szrj * @param __first Start of range.
535*38fd1498Szrj * @param __last End of range.
536*38fd1498Szrj * @param __comp Comparison functor to use.
537*38fd1498Szrj * @return True if range is a heap, false otherwise.
538*38fd1498Szrj * @ingroup heap_algorithms
539*38fd1498Szrj */
540*38fd1498Szrj template<typename _RandomAccessIterator, typename _Compare>
541*38fd1498Szrj inline bool
542*38fd1498Szrj is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
543*38fd1498Szrj _Compare __comp)
544*38fd1498Szrj {
545*38fd1498Szrj // concept requirements
546*38fd1498Szrj __glibcxx_function_requires(_RandomAccessIteratorConcept<
547*38fd1498Szrj _RandomAccessIterator>)
548*38fd1498Szrj __glibcxx_requires_valid_range(__first, __last);
549*38fd1498Szrj __glibcxx_requires_irreflexive_pred(__first, __last, __comp);
550*38fd1498Szrj
551*38fd1498Szrj const auto __dist = std::distance(__first, __last);
552*38fd1498Szrj typedef __decltype(__comp) _Cmp;
553*38fd1498Szrj __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp));
554*38fd1498Szrj return std::__is_heap_until(__first, __dist, __cmp) == __dist;
555*38fd1498Szrj }
556*38fd1498Szrj #endif
557*38fd1498Szrj
558*38fd1498Szrj _GLIBCXX_END_NAMESPACE_VERSION
559*38fd1498Szrj } // namespace
560*38fd1498Szrj
561*38fd1498Szrj #endif /* _STL_HEAP_H */
562