xref: /dflybsd-src/contrib/gcc-8.0/libstdc++-v3/include/bits/stl_heap.h (revision 38fd149817dfbff97799f62fcb70be98c4e32523)
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