std::partition (3) Linux Manual Page
std::partition – std::partition
Synopsis
Defined in header <algorithm>
template< class BidirIt, class UnaryPredicate > (until C++11)
BidirIt partition( BidirIt first, BidirIt last, UnaryPredicate p );
template< class ForwardIt, class UnaryPredicate > (since C++11)
ForwardIt partition( ForwardIt first, ForwardIt last, UnaryPredicate p ); (until C++20)
template< class ForwardIt, class UnaryPredicate > (1) (since C++20)
constexpr ForwardIt partition( ForwardIt first, ForwardIt last, UnaryPredicate p );
template< class ExecutionPolicy, class ForwardIt, class UnaryPredicate >
ForwardIt partition( ExecutionPolicy&& policy, (2) (since C++17)
ForwardIt first, ForwardIt last, UnaryPredicate p );
1) Reorders the elements in the range [first, last) in such a way that all elements for which the predicate p returns true precede the elements for which predicate p returns false. Relative order of the elements is not preserved.
2) Same as (1), but executed according to policy. This overload does not participate in overload resolution unless std::is_execution_policy_v<std::decay_t<ExecutionPolicy>> is true
Parameters
first, last – the range of elements to reorder
policy – the execution policy to use. See execution_policy for details.
p – The expression p(v) must be convertible to bool for every argument v of type (possibly const) VT, where VT is the value type of ForwardIt, regardless of value_category, and must not modify v. Thus, a parameter type of VT&is not allowed
Type requirements
–
BidirIt must meet the requirements of LegacyBidirectionalIterator.
–
ForwardIt must meet the requirements of ValueSwappable and LegacyForwardIterator. However, the operation is more efficient if ForwardIt also satisfies the requirements of LegacyBidirectionalIterator
–
UnaryPredicate must meet the requirements of Predicate.
Return value
Iterator to the first element of the second group.
Complexity
Given N = std::distance(first,last),
1) Exactly N applications of the predicate. At most N/2 swaps if ForwardIt meets the requirements of LegacyBidirectionalIterator, and at most N swaps otherwise.
2) O(N log N) swaps and O(N) applications of the predicate.
Exceptions
The overload with a template parameter named ExecutionPolicy reports errors as follows:
* If execution of a function invoked as part of the algorithm throws an exception and ExecutionPolicy is one of the standard_policies, std::terminate is called. For any other ExecutionPolicy, the behavior is implementation-defined.
* If the algorithm fails to allocate memory, std::bad_alloc is thrown.
Possible implementation
Example
// Run this code
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
#include <forward_list>
template <class ForwardIt>
void quicksort(ForwardIt first, ForwardIt last)
{
if (first == last)
return;
auto pivot = *std::next(first, std::distance(first, last) / 2);
ForwardIt middle1 = std::partition(first, last,
[pivot](const auto &em) { return em < pivot; });
ForwardIt middle2 = std::partition(middle1, last,
[pivot](const auto &em) { return !(pivot < em); });
quicksort(first, middle1);
quicksort(middle2, last);
}
int main()
{
std::vector<int> v = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
std::cout << "Original vector:\n ";
for (int elem : v)
std::cout << elem << ' ';
auto it = std::partition(v.begin(), v.end(), [](int i) { return i % 2 == 0; });
std::cout << "\nPartitioned vector:\n ";
std::copy(std::begin(v), it, std::ostream_iterator<int>(std::cout, " "));
std::cout << " * ";
std::copy(it, std::end(v), std::ostream_iterator<int>(std::cout, " "));
std::forward_list<int> fl = {1, 30, -4, 3, 5, -4, 1, 6, -8, 2, -5, 64, 1, 92};
std::cout << "\nUnsorted list:\n ";
for (int n : fl)
std::cout << n << ' ';
std::cout << '\n';
quicksort(std::begin(fl), std::end(fl));
std::cout << "Sorted using quicksort:\n ";
for (int fi : fl)
std::cout << fi << ' ';
std::cout << '\n';
}
Output:
See also
is_partitioned determines if the range is partitioned by the given predicate
(C++11)
stable_partition (function template)
