124 lines
4.1 KiB
C++
124 lines
4.1 KiB
C++
/*
|
|
Copyright 2008 Adobe Systems Incorporated
|
|
|
|
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
|
|
Revision history:
|
|
January 2008 mtc Version for Adobe Source Library
|
|
January 2013 mtc Version for Boost.Algorithm
|
|
|
|
*/
|
|
|
|
/**************************************************************************************************/
|
|
|
|
/*!
|
|
\author Marshall Clow
|
|
\date January 2008
|
|
*/
|
|
|
|
#ifndef BOOST_ALGORITHM_GATHER_HPP
|
|
#define BOOST_ALGORITHM_GATHER_HPP
|
|
|
|
#include <algorithm> // for std::stable_partition
|
|
#include <functional>
|
|
|
|
#include <boost/bind.hpp> // for boost::bind
|
|
#include <boost/range/begin.hpp> // for boost::begin(range)
|
|
#include <boost/range/end.hpp> // for boost::end(range)
|
|
|
|
|
|
/**************************************************************************************************/
|
|
/*!
|
|
\defgroup gather gather
|
|
\ingroup mutating_algorithm
|
|
|
|
\c gather() takes a collection of elements defined by a pair of iterators and moves
|
|
the ones satisfying a predicate to them to a position (called the pivot) within
|
|
the sequence. The algorithm is stable. The result is a pair of iterators that
|
|
contains the items that satisfy the predicate.
|
|
|
|
Given an sequence containing:
|
|
<pre>
|
|
0 1 2 3 4 5 6 7 8 9
|
|
</pre>
|
|
|
|
a call to gather ( arr, arr + 10, arr + 4, IsEven ()) will result in:
|
|
|
|
<pre>
|
|
1 3 0 2 4 6 8 5 7 9
|
|
|---|-----|
|
|
first | second
|
|
pivot
|
|
</pre>
|
|
|
|
|
|
The problem is broken down into two basic steps, namely, moving the items before the pivot
|
|
and then moving the items from the pivot to the end. These "moves" are done with calls to
|
|
stable_partition.
|
|
|
|
\par Storage Requirements:
|
|
|
|
The algorithm uses stable_partition, which will attempt to allocate temporary memory,
|
|
but will work in-situ if there is none available.
|
|
|
|
\par Time Complexity:
|
|
|
|
If there is sufficient memory available, the run time is linear in <code>N</code>.
|
|
If there is not any memory available, then the run time is <code>O(N log N)</code>.
|
|
*/
|
|
|
|
/**************************************************************************************************/
|
|
|
|
namespace boost { namespace algorithm {
|
|
|
|
/**************************************************************************************************/
|
|
|
|
/*!
|
|
\ingroup gather
|
|
\brief iterator-based gather implementation
|
|
*/
|
|
|
|
template <
|
|
typename BidirectionalIterator, // Iter models BidirectionalIterator
|
|
typename Pred> // Pred models UnaryPredicate
|
|
std::pair<BidirectionalIterator, BidirectionalIterator> gather
|
|
( BidirectionalIterator first, BidirectionalIterator last, BidirectionalIterator pivot, Pred pred )
|
|
{
|
|
// The first call partitions everything up to (but not including) the pivot element,
|
|
// while the second call partitions the rest of the sequence.
|
|
return std::make_pair (
|
|
std::stable_partition ( first, pivot, !boost::bind<bool> ( pred, _1 )),
|
|
std::stable_partition ( pivot, last, boost::bind<bool> ( pred, _1 )));
|
|
}
|
|
|
|
/**************************************************************************************************/
|
|
|
|
/*!
|
|
\ingroup gather
|
|
\brief range-based gather implementation
|
|
*/
|
|
|
|
template <
|
|
typename BidirectionalRange, //
|
|
typename Pred> // Pred models UnaryPredicate
|
|
std::pair<
|
|
typename boost::range_iterator<const BidirectionalRange>::type,
|
|
typename boost::range_iterator<const BidirectionalRange>::type>
|
|
gather (
|
|
const BidirectionalRange &range,
|
|
typename boost::range_iterator<const BidirectionalRange>::type pivot,
|
|
Pred pred )
|
|
{
|
|
return boost::algorithm::gather ( boost::begin ( range ), boost::end ( range ), pivot, pred );
|
|
}
|
|
|
|
/**************************************************************************************************/
|
|
|
|
}} // namespace
|
|
|
|
/**************************************************************************************************/
|
|
|
|
#endif
|
|
|