gather.hpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. /*
  2. Copyright 2008 Adobe Systems Incorporated
  3. Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. Revision history:
  6. January 2008 mtc Version for Adobe Source Library
  7. January 2013 mtc Version for Boost.Algorithm
  8. */
  9. /**************************************************************************************************/
  10. /*!
  11. \author Marshall Clow
  12. \date January 2008
  13. */
  14. #ifndef BOOST_ALGORITHM_GATHER_HPP
  15. #define BOOST_ALGORITHM_GATHER_HPP
  16. #include <algorithm> // for std::stable_partition
  17. #include <functional>
  18. #include <utility> // for std::make_pair
  19. #include <boost/config.hpp>
  20. #include <boost/bind/bind.hpp> // for boost::bind
  21. #include <boost/range/begin.hpp> // for boost::begin(range)
  22. #include <boost/range/end.hpp> // for boost::end(range)
  23. /**************************************************************************************************/
  24. /*!
  25. \defgroup gather gather
  26. \ingroup mutating_algorithm
  27. \c gather() takes a collection of elements defined by a pair of iterators and moves
  28. the ones satisfying a predicate to them to a position (called the pivot) within
  29. the sequence. The algorithm is stable. The result is a pair of iterators that
  30. contains the items that satisfy the predicate.
  31. Given an sequence containing:
  32. <pre>
  33. 0 1 2 3 4 5 6 7 8 9
  34. </pre>
  35. a call to gather ( arr, arr + 10, arr + 4, IsEven ()) will result in:
  36. <pre>
  37. 1 3 0 2 4 6 8 5 7 9
  38. |---|-----|
  39. first | second
  40. pivot
  41. </pre>
  42. The problem is broken down into two basic steps, namely, moving the items before the pivot
  43. and then moving the items from the pivot to the end. These "moves" are done with calls to
  44. stable_partition.
  45. \par Storage Requirements:
  46. The algorithm uses stable_partition, which will attempt to allocate temporary memory,
  47. but will work in-situ if there is none available.
  48. \par Time Complexity:
  49. If there is sufficient memory available, the run time is linear in <code>N</code>.
  50. If there is not any memory available, then the run time is <code>O(N log N)</code>.
  51. */
  52. /**************************************************************************************************/
  53. namespace boost { namespace algorithm {
  54. /**************************************************************************************************/
  55. /*!
  56. \ingroup gather
  57. \brief iterator-based gather implementation
  58. */
  59. template <
  60. typename BidirectionalIterator, // models BidirectionalIterator
  61. typename Pred> // models UnaryPredicate
  62. std::pair<BidirectionalIterator, BidirectionalIterator> gather
  63. ( BidirectionalIterator first, BidirectionalIterator last, BidirectionalIterator pivot, Pred pred )
  64. {
  65. // The first call partitions everything up to (but not including) the pivot element,
  66. // while the second call partitions the rest of the sequence.
  67. using namespace boost::placeholders;
  68. return std::make_pair (
  69. std::stable_partition ( first, pivot, !boost::bind<bool> ( pred, _1 )),
  70. std::stable_partition ( pivot, last, boost::bind<bool> ( pred, _1 )));
  71. }
  72. /**************************************************************************************************/
  73. /*!
  74. \ingroup gather
  75. \brief range-based gather implementation
  76. */
  77. template <
  78. typename BidirectionalRange, //
  79. typename Pred> // Pred models UnaryPredicate
  80. std::pair<
  81. typename boost::range_iterator<const BidirectionalRange>::type,
  82. typename boost::range_iterator<const BidirectionalRange>::type>
  83. gather (
  84. const BidirectionalRange &range,
  85. typename boost::range_iterator<const BidirectionalRange>::type pivot,
  86. Pred pred )
  87. {
  88. return boost::algorithm::gather ( boost::begin ( range ), boost::end ( range ), pivot, pred );
  89. }
  90. /**************************************************************************************************/
  91. }} // namespace
  92. /**************************************************************************************************/
  93. #endif