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