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