]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/libstdc++/include/bits/stl_heap.h
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / libstdc++ / include / bits / stl_heap.h
1 // Heap implementation -*- C++ -*-
2
3 // Copyright (C) 2001, 2004, 2005, 2006 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library.  This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 2, or (at your option)
9 // any later version.
10
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
15
16 // You should have received a copy of the GNU General Public License along
17 // with this library; see the file COPYING.  If not, write to the Free
18 // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19 // USA.
20
21 // As a special exception, you may use this file as part of a free software
22 // library without restriction.  Specifically, if other files instantiate
23 // templates or use macros or inline functions from this file, or you compile
24 // this file and link it with other files to produce an executable, this
25 // file does not by itself cause the resulting executable to be covered by
26 // the GNU General Public License.  This exception does not however
27 // invalidate any other reasons why the executable file might be covered by
28 // the GNU General Public License.
29
30 /*
31  *
32  * Copyright (c) 1994
33  * Hewlett-Packard Company
34  *
35  * Permission to use, copy, modify, distribute and sell this software
36  * and its documentation for any purpose is hereby granted without fee,
37  * provided that the above copyright notice appear in all copies and
38  * that both that copyright notice and this permission notice appear
39  * in supporting documentation.  Hewlett-Packard Company makes no
40  * representations about the suitability of this software for any
41  * purpose.  It is provided "as is" without express or implied warranty.
42  *
43  * Copyright (c) 1997
44  * Silicon Graphics Computer Systems, Inc.
45  *
46  * Permission to use, copy, modify, distribute and sell this software
47  * and its documentation for any purpose is hereby granted without fee,
48  * provided that the above copyright notice appear in all copies and
49  * that both that copyright notice and this permission notice appear
50  * in supporting documentation.  Silicon Graphics makes no
51  * representations about the suitability of this software for any
52  * purpose.  It is provided "as is" without express or implied warranty.
53  */
54
55 /** @file stl_heap.h
56  *  This is an internal header file, included by other library headers.
57  *  You should not attempt to use it directly.
58  */
59
60 #ifndef _STL_HEAP_H
61 #define _STL_HEAP_H 1
62
63 #include <debug/debug.h>
64
65 _GLIBCXX_BEGIN_NAMESPACE(std)
66
67   // is_heap, a predicate testing whether or not a range is
68   // a heap.  This function is an extension, not part of the C++
69   // standard.
70   template<typename _RandomAccessIterator, typename _Distance>
71     bool
72     __is_heap(_RandomAccessIterator __first, _Distance __n)
73     {
74       _Distance __parent = 0;
75       for (_Distance __child = 1; __child < __n; ++__child)
76         {
77           if (__first[__parent] < __first[__child])
78             return false;
79           if ((__child & 1) == 0)
80             ++__parent;
81         }
82       return true;
83     }
84
85   template<typename _RandomAccessIterator, typename _Distance,
86            typename _StrictWeakOrdering>
87     bool
88     __is_heap(_RandomAccessIterator __first, _StrictWeakOrdering __comp,
89               _Distance __n)
90     {
91       _Distance __parent = 0;
92       for (_Distance __child = 1; __child < __n; ++__child)
93         {
94           if (__comp(__first[__parent], __first[__child]))
95             return false;
96           if ((__child & 1) == 0)
97             ++__parent;
98         }
99       return true;
100     }
101
102   template<typename _RandomAccessIterator>
103     bool
104     __is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
105     { return std::__is_heap(__first, std::distance(__first, __last)); }
106
107   template<typename _RandomAccessIterator, typename _StrictWeakOrdering>
108     bool
109     __is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
110             _StrictWeakOrdering __comp)
111     { return std::__is_heap(__first, __comp, std::distance(__first, __last)); }
112
113   // Heap-manipulation functions: push_heap, pop_heap, make_heap, sort_heap.
114
115   template<typename _RandomAccessIterator, typename _Distance, typename _Tp>
116     void
117     __push_heap(_RandomAccessIterator __first,
118                 _Distance __holeIndex, _Distance __topIndex, _Tp __value)
119     {
120       _Distance __parent = (__holeIndex - 1) / 2;
121       while (__holeIndex > __topIndex && *(__first + __parent) < __value)
122         {
123           *(__first + __holeIndex) = *(__first + __parent);
124           __holeIndex = __parent;
125           __parent = (__holeIndex - 1) / 2;
126         }
127       *(__first + __holeIndex) = __value;
128     }
129
130   /**
131    *  @brief  Push an element onto a heap.
132    *  @param  first  Start of heap.
133    *  @param  last   End of heap + element.
134    *  @ingroup heap
135    *
136    *  This operation pushes the element at last-1 onto the valid heap over the
137    *  range [first,last-1).  After completion, [first,last) is a valid heap.
138   */
139   template<typename _RandomAccessIterator>
140     inline void
141     push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
142     {
143       typedef typename iterator_traits<_RandomAccessIterator>::value_type
144           _ValueType;
145       typedef typename iterator_traits<_RandomAccessIterator>::difference_type
146           _DistanceType;
147
148       // concept requirements
149       __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
150             _RandomAccessIterator>)
151       __glibcxx_function_requires(_LessThanComparableConcept<_ValueType>)
152       __glibcxx_requires_valid_range(__first, __last);
153       //      __glibcxx_requires_heap(__first, __last - 1);
154
155       std::__push_heap(__first, _DistanceType((__last - __first) - 1),
156                        _DistanceType(0), _ValueType(*(__last - 1)));
157     }
158
159   template<typename _RandomAccessIterator, typename _Distance, typename _Tp,
160             typename _Compare>
161     void
162     __push_heap(_RandomAccessIterator __first, _Distance __holeIndex,
163                 _Distance __topIndex, _Tp __value, _Compare __comp)
164     {
165       _Distance __parent = (__holeIndex - 1) / 2;
166       while (__holeIndex > __topIndex
167              && __comp(*(__first + __parent), __value))
168         {
169           *(__first + __holeIndex) = *(__first + __parent);
170           __holeIndex = __parent;
171           __parent = (__holeIndex - 1) / 2;
172         }
173       *(__first + __holeIndex) = __value;
174     }
175
176   /**
177    *  @brief  Push an element onto a heap using comparison functor.
178    *  @param  first  Start of heap.
179    *  @param  last   End of heap + element.
180    *  @param  comp   Comparison functor.
181    *  @ingroup heap
182    *
183    *  This operation pushes the element at last-1 onto the valid heap over the
184    *  range [first,last-1).  After completion, [first,last) is a valid heap.
185    *  Compare operations are performed using comp.
186   */
187   template<typename _RandomAccessIterator, typename _Compare>
188     inline void
189     push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
190               _Compare __comp)
191     {
192       typedef typename iterator_traits<_RandomAccessIterator>::value_type
193           _ValueType;
194       typedef typename iterator_traits<_RandomAccessIterator>::difference_type
195           _DistanceType;
196
197       // concept requirements
198       __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
199             _RandomAccessIterator>)
200       __glibcxx_requires_valid_range(__first, __last);
201       __glibcxx_requires_heap_pred(__first, __last - 1, __comp);
202
203       std::__push_heap(__first, _DistanceType((__last - __first) - 1),
204                        _DistanceType(0), _ValueType(*(__last - 1)), __comp);
205     }
206
207   template<typename _RandomAccessIterator, typename _Distance, typename _Tp>
208     void
209     __adjust_heap(_RandomAccessIterator __first, _Distance __holeIndex,
210                   _Distance __len, _Tp __value)
211     {
212       const _Distance __topIndex = __holeIndex;
213       _Distance __secondChild = 2 * __holeIndex + 2;
214       while (__secondChild < __len)
215         {
216           if (*(__first + __secondChild) < *(__first + (__secondChild - 1)))
217             __secondChild--;
218           *(__first + __holeIndex) = *(__first + __secondChild);
219           __holeIndex = __secondChild;
220           __secondChild = 2 * (__secondChild + 1);
221         }
222       if (__secondChild == __len)
223         {
224           *(__first + __holeIndex) = *(__first + (__secondChild - 1));
225           __holeIndex = __secondChild - 1;
226         }
227       std::__push_heap(__first, __holeIndex, __topIndex, __value);
228     }
229
230   template<typename _RandomAccessIterator, typename _Tp>
231     inline void
232     __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
233                _RandomAccessIterator __result, _Tp __value)
234     {
235       typedef typename iterator_traits<_RandomAccessIterator>::difference_type
236         _Distance;
237       *__result = *__first;
238       std::__adjust_heap(__first, _Distance(0), _Distance(__last - __first),
239                          __value);
240     }
241
242   /**
243    *  @brief  Pop an element off a heap.
244    *  @param  first  Start of heap.
245    *  @param  last   End of heap.
246    *  @ingroup heap
247    *
248    *  This operation pops the top of the heap.  The elements first and last-1
249    *  are swapped and [first,last-1) is made into a heap.
250   */
251   template<typename _RandomAccessIterator>
252     inline void
253     pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
254     {
255       typedef typename iterator_traits<_RandomAccessIterator>::value_type
256         _ValueType;
257
258       // concept requirements
259       __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
260             _RandomAccessIterator>)
261       __glibcxx_function_requires(_LessThanComparableConcept<_ValueType>)
262       __glibcxx_requires_valid_range(__first, __last);
263       __glibcxx_requires_heap(__first, __last);
264
265       std::__pop_heap(__first, __last - 1, __last - 1,
266                       _ValueType(*(__last - 1)));
267     }
268
269   template<typename _RandomAccessIterator, typename _Distance,
270            typename _Tp, typename _Compare>
271     void
272     __adjust_heap(_RandomAccessIterator __first, _Distance __holeIndex,
273                   _Distance __len, _Tp __value, _Compare __comp)
274     {
275       const _Distance __topIndex = __holeIndex;
276       _Distance __secondChild = 2 * __holeIndex + 2;
277       while (__secondChild < __len)
278         {
279           if (__comp(*(__first + __secondChild),
280                      *(__first + (__secondChild - 1))))
281             __secondChild--;
282           *(__first + __holeIndex) = *(__first + __secondChild);
283           __holeIndex = __secondChild;
284           __secondChild = 2 * (__secondChild + 1);
285         }
286       if (__secondChild == __len)
287         {
288           *(__first + __holeIndex) = *(__first + (__secondChild - 1));
289           __holeIndex = __secondChild - 1;
290         }
291       std::__push_heap(__first, __holeIndex, __topIndex, __value, __comp);
292     }
293
294   template<typename _RandomAccessIterator, typename _Tp, typename _Compare>
295     inline void
296     __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
297                _RandomAccessIterator __result, _Tp __value, _Compare __comp)
298     {
299       typedef typename iterator_traits<_RandomAccessIterator>::difference_type
300         _Distance;
301       *__result = *__first;
302       std::__adjust_heap(__first, _Distance(0), _Distance(__last - __first),
303                          __value, __comp);
304     }
305
306   /**
307    *  @brief  Pop an element off a heap using comparison functor.
308    *  @param  first  Start of heap.
309    *  @param  last   End of heap.
310    *  @param  comp   Comparison functor to use.
311    *  @ingroup heap
312    *
313    *  This operation pops the top of the heap.  The elements first and last-1
314    *  are swapped and [first,last-1) is made into a heap.  Comparisons are
315    *  made using comp.
316   */
317   template<typename _RandomAccessIterator, typename _Compare>
318     inline void
319     pop_heap(_RandomAccessIterator __first,
320              _RandomAccessIterator __last, _Compare __comp)
321     {
322       // concept requirements
323       __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
324             _RandomAccessIterator>)
325       __glibcxx_requires_valid_range(__first, __last);
326       __glibcxx_requires_heap_pred(__first, __last, __comp);
327
328       typedef typename iterator_traits<_RandomAccessIterator>::value_type
329         _ValueType;
330       std::__pop_heap(__first, __last - 1, __last - 1,
331                       _ValueType(*(__last - 1)), __comp);
332     }
333
334   /**
335    *  @brief  Construct a heap over a range.
336    *  @param  first  Start of heap.
337    *  @param  last   End of heap.
338    *  @ingroup heap
339    *
340    *  This operation makes the elements in [first,last) into a heap.
341   */
342   template<typename _RandomAccessIterator>
343     void
344     make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
345     {
346       typedef typename iterator_traits<_RandomAccessIterator>::value_type
347           _ValueType;
348       typedef typename iterator_traits<_RandomAccessIterator>::difference_type
349           _DistanceType;
350
351       // concept requirements
352       __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
353             _RandomAccessIterator>)
354       __glibcxx_function_requires(_LessThanComparableConcept<_ValueType>)
355       __glibcxx_requires_valid_range(__first, __last);
356
357       if (__last - __first < 2)
358         return;
359
360       const _DistanceType __len = __last - __first;
361       _DistanceType __parent = (__len - 2) / 2;
362       while (true)
363         {
364           std::__adjust_heap(__first, __parent, __len,
365                              _ValueType(*(__first + __parent)));
366           if (__parent == 0)
367             return;
368           __parent--;
369         }
370     }
371
372   /**
373    *  @brief  Construct a heap over a range using comparison functor.
374    *  @param  first  Start of heap.
375    *  @param  last   End of heap.
376    *  @param  comp   Comparison functor to use.
377    *  @ingroup heap
378    *
379    *  This operation makes the elements in [first,last) into a heap.
380    *  Comparisons are made using comp.
381   */
382   template<typename _RandomAccessIterator, typename _Compare>
383     inline void
384     make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
385               _Compare __comp)
386     {
387       typedef typename iterator_traits<_RandomAccessIterator>::value_type
388           _ValueType;
389       typedef typename iterator_traits<_RandomAccessIterator>::difference_type
390           _DistanceType;
391
392       // concept requirements
393       __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
394             _RandomAccessIterator>)
395       __glibcxx_requires_valid_range(__first, __last);
396
397       if (__last - __first < 2)
398         return;
399
400       const _DistanceType __len = __last - __first;
401       _DistanceType __parent = (__len - 2) / 2;
402       while (true)
403         {
404           std::__adjust_heap(__first, __parent, __len,
405                              _ValueType(*(__first + __parent)), __comp);
406           if (__parent == 0)
407             return;
408           __parent--;
409         }
410     }
411
412   /**
413    *  @brief  Sort a heap.
414    *  @param  first  Start of heap.
415    *  @param  last   End of heap.
416    *  @ingroup heap
417    *
418    *  This operation sorts the valid heap in the range [first,last).
419   */
420   template<typename _RandomAccessIterator>
421     void
422     sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last)
423     {
424       // concept requirements
425       __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
426             _RandomAccessIterator>)
427       __glibcxx_function_requires(_LessThanComparableConcept<
428             typename iterator_traits<_RandomAccessIterator>::value_type>)
429       __glibcxx_requires_valid_range(__first, __last);
430       //      __glibcxx_requires_heap(__first, __last);
431
432       while (__last - __first > 1)
433         std::pop_heap(__first, _RandomAccessIterator(__last--));
434     }
435
436   /**
437    *  @brief  Sort a heap using comparison functor.
438    *  @param  first  Start of heap.
439    *  @param  last   End of heap.
440    *  @param  comp   Comparison functor to use.
441    *  @ingroup heap
442    *
443    *  This operation sorts the valid heap in the range [first,last).
444    *  Comparisons are made using comp.
445   */
446   template<typename _RandomAccessIterator, typename _Compare>
447     void
448     sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last,
449               _Compare __comp)
450     {
451       // concept requirements
452       __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
453             _RandomAccessIterator>)
454       __glibcxx_requires_valid_range(__first, __last);
455       __glibcxx_requires_heap_pred(__first, __last, __comp);
456
457       while (__last - __first > 1)
458         std::pop_heap(__first, _RandomAccessIterator(__last--), __comp);
459     }
460
461 _GLIBCXX_END_NAMESPACE
462
463 #endif /* _STL_HEAP_H */