Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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