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 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