Namespaces
Variants
Views
Actions

Difference between revisions of "cpp/algorithm/ranges/partition point"

From cppreference.com
< cpp‎ | algorithm‎ | ranges
m (Example: refactored a bit.)
m (fmt)
 
(2 intermediate revisions by 2 users not shown)
Line 2: Line 2:
 
{{cpp/algorithm/ranges/navbar}}
 
{{cpp/algorithm/ranges/navbar}}
 
{{dcl begin}}
 
{{dcl begin}}
{{dcl header | algorithm}}
+
{{dcl header|algorithm}}
{{dcl h | Call signature}}
+
{{dcl h|Call signature}}
{{dcl | num=1 | since=c++20 |1=
+
{{dcl|num=1|since=c++20|1=
template< std::forward_iterator I,
+
template< std::forward_iterator I, std::sentinel_for<I> S,
          std::sentinel_for<I> S,
+
 
           class Proj = std::identity,
 
           class Proj = std::identity,
           std::indirect_unary_predicate<
+
           std::indirect_unary_predicate<std::projected<I, Proj>> Pred >
              std::projected<I, Proj>> Pred >
+
 
constexpr I
 
constexpr I
partition_point( I first,
+
    partition_point( I first, S last, Pred pred, Proj proj = {} );
                S last,
+
                Pred pred,
+
                Proj proj = {} );
+
 
}}
 
}}
{{dcl | num=2 | since=c++20 |1=
+
{{dcl|num=2|since=c++20|1=
 
template< ranges::forward_range R,
 
template< ranges::forward_range R,
 
           class Proj = std::identity,
 
           class Proj = std::identity,
Line 22: Line 17:
 
               std::projected<ranges::iterator_t<R>, Proj>> Pred >
 
               std::projected<ranges::iterator_t<R>, Proj>> Pred >
 
constexpr ranges::borrowed_iterator_t<R>
 
constexpr ranges::borrowed_iterator_t<R>
partition_point( R&& r,
+
    partition_point( R&& r, Pred pred, Proj proj = {} );
                Pred pred,
+
                Proj proj = {} );
+
 
}}
 
}}
 
{{dcl end}}
 
{{dcl end}}
  
Examines the partitioned (as if by {{lc|ranges::partition}}) range {{tt|[first, last)}} or {{tt|r}} and locates the end of the first partition, that is, the projected element that does not satisfy {{tt|pred}} or {{tt|last}} if all projected elements satisfy {{tt|pred}}.
+
Examines the partitioned (as if by {{lc|ranges::partition}}) range {{range|first|last}} or {{c|r}} and locates the end of the first partition, that is, the projected element that does not satisfy {{c|pred}} or {{c|last}} if all projected elements satisfy {{c|pred}}.
  
 
{{cpp/ranges/niebloid}}
 
{{cpp/ranges/niebloid}}
Line 34: Line 27:
 
===Parameters===
 
===Parameters===
 
{{par begin}}
 
{{par begin}}
{{par | first, last | iterator-sentinel defining the partially-ordered range to examine}}
+
{{par|first, last|iterator-sentinel defining the partially-ordered range to examine}}
{{par | r | the partially-ordered range to examine}}
+
{{par|r|the partially-ordered range to examine}}
{{par | pred | predicate to apply to the projected elements}}
+
{{par|pred|predicate to apply to the projected elements}}
{{par | proj | projection to apply to the elements}}
+
{{par|proj|projection to apply to the elements}}
 
{{par end}}
 
{{par end}}
  
 
===Return value===
 
===Return value===
The iterator past the end of the first partition within {{tt|[first, last)}} or the iterator equal to {{tt|last}} if all projected elements satisfy {{tt|pred}}.
+
The iterator past the end of the first partition within {{range|first|last}} or the iterator equal to {{c|last}} if all projected elements satisfy {{c|pred}}.
  
 
===Complexity===
 
===Complexity===
Given {{c|1=N = ranges::distance(first, last)}}, performs {{math|O(log N)}} applications of the predicate {{tt|pred}} and projection {{tt|proj}}.
+
Given {{c|1=N = ranges::distance(first, last)}}, performs {{math|O(log N)}} applications of the predicate {{c|pred}} and projection {{c|proj}}.
  
 
However, if sentinels don't model {{c|std::sized_sentinel_for<I>}}, the number of iterator increments is {{math|O(N)}}.
 
However, if sentinels don't model {{c|std::sized_sentinel_for<I>}}, the number of iterator increments is {{math|O(N)}}.
Line 52: Line 45:
  
 
===Example===
 
===Example===
{{example
+
{{example|code=
|
+
| code=
+
 
#include <algorithm>
 
#include <algorithm>
 
#include <array>
 
#include <array>
Line 60: Line 51:
 
#include <iterator>
 
#include <iterator>
  
int main()
+
auto print_seq = [](auto rem, auto first, auto last)
 
{
 
{
     std::array v = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
     for (std::cout << rem; first != last; std::cout << *first++ << ' ') {}
 +
    std::cout << '\n';
 +
};
  
    namespace ranges = std::ranges;
+
int main()
    auto is_even = [](int i){ return i % 2 == 0; };
+
{
     auto to_console = std::ostream_iterator<int>(std::cout, " ");
+
     std::array v {1, 2, 3, 4, 5, 6, 7, 8, 9};
  
     ranges::partition(v, is_even);
+
     auto is_even = [](int i) { return i % 2 == 0; };
  
     std::cout << "After partitioning, v: ";
+
     std::ranges::partition(v, is_even);
    ranges::copy(v.cbegin(), v.cend(), to_console);
+
    print_seq("After partitioning, v: ", v.cbegin(), v.cend());
  
     const auto pp = ranges::partition_point(v, is_even);
+
     const auto pp = std::ranges::partition_point(v, is_even);
 +
    const auto i = std::ranges::distance(v.cbegin(), pp);
 +
    std::cout << "Partition point is at " << i << "; v[" << i << "] = " << *pp << '\n';
  
     std::cout << "\nPartition point is at distance "
+
     print_seq("First partition (all even elements): ", v.cbegin(), pp);
              << ranges::distance(v.cbegin(), pp)
+
     print_seq("Second partition (all odd elements): ", pp, v.cend());
              << " and points to " << *pp
+
              << "\nFirst partition (all even elements): ";
+
    ranges::copy(v.cbegin(), pp, to_console);
+
     std::cout << "\nSecond partition (all odd elements): ";
+
    ranges::copy(pp, v.cend(), to_console);
+
 
}
 
}
| output=
+
|p=true
After partitioning, v: 8 2 6 4 5 3 7 1 9  
+
|output=
Partition point is at distance 4 and points to 5
+
After partitioning, v: 2 4 6 8 5 3 7 1 9
First partition (all even elements): 8 2 6 4  
+
Partition point is at 4; v[4] = 5
 +
First partition (all even elements): 2 4 6 8
 
Second partition (all odd elements): 5 3 7 1 9
 
Second partition (all odd elements): 5 3 7 1 9
 
}}
 
}}
Line 92: Line 83:
 
===See also===
 
===See also===
 
{{dsc begin}}
 
{{dsc begin}}
{{dsc inc | cpp/algorithm/ranges/dsc is_sorted}}
+
{{dsc inc|cpp/algorithm/ranges/dsc is_sorted}}
{{dsc inc | cpp/algorithm/ranges/dsc lower_bound}}
+
{{dsc inc|cpp/algorithm/ranges/dsc lower_bound}}
{{dsc inc | cpp/algorithm/dsc partition_point}}
+
{{dsc inc|cpp/algorithm/dsc partition_point}}
 
{{dsc end}}
 
{{dsc end}}
  
 
{{langlinks|de|es|fr|it|ja|pt|ru|zh}}
 
{{langlinks|de|es|fr|it|ja|pt|ru|zh}}

Latest revision as of 03:48, 15 April 2023

 
 
Algorithm library
Constrained algorithms and algorithms on ranges (C++20)
Constrained algorithms, e.g. ranges::copy, ranges::sort, ...
Execution policies (C++17)
Non-modifying sequence operations
Batch operations
(C++17)
Search operations
(C++11)                (C++11)(C++11)

Modifying sequence operations
Copy operations
(C++11)
(C++11)
Swap operations
Transformation operations
Generation operations
Removing operations
Order-changing operations
(until C++17)(C++11)
(C++20)(C++20)
Sampling operations
(C++17)

Sorting and related operations
Partitioning operations
Sorting operations
Binary search operations
(on partitioned ranges)
Set operations (on sorted ranges)
Merge operations (on sorted ranges)
Heap operations
Minimum/maximum operations
(C++11)
(C++17)
Lexicographical comparison operations
Permutation operations
C library
Numeric operations
Operations on uninitialized memory
 
Constrained algorithms
All names in this menu belong to namespace std::ranges
Non-modifying sequence operations
Modifying sequence operations
Partitioning operations
partition_point
  
Sorting operations
Binary search operations (on sorted ranges)
       
       
Set operations (on sorted ranges)
Heap operations
Minimum/maximum operations
       
       
Permutation operations
Fold operations
Numeric operations
(C++23)            
Operations on uninitialized storage
Return types
 
Defined in header <algorithm>
Call signature
template< std::forward_iterator I, std::sentinel_for<I> S,

          class Proj = std::identity,
          std::indirect_unary_predicate<std::projected<I, Proj>> Pred >
constexpr I

    partition_point( I first, S last, Pred pred, Proj proj = {} );
(1) (since C++20)
template< ranges::forward_range R,

          class Proj = std::identity,
          std::indirect_unary_predicate<
              std::projected<ranges::iterator_t<R>, Proj>> Pred >
constexpr ranges::borrowed_iterator_t<R>

    partition_point( R&& r, Pred pred, Proj proj = {} );
(2) (since C++20)

Examines the partitioned (as if by ranges::partition) range [firstlast) or r and locates the end of the first partition, that is, the projected element that does not satisfy pred or last if all projected elements satisfy pred.

The function-like entities described on this page are niebloids, that is:

In practice, they may be implemented as function objects, or with special compiler extensions.

Contents

[edit] Parameters

first, last - iterator-sentinel defining the partially-ordered range to examine
r - the partially-ordered range to examine
pred - predicate to apply to the projected elements
proj - projection to apply to the elements

[edit] Return value

The iterator past the end of the first partition within [firstlast) or the iterator equal to last if all projected elements satisfy pred.

[edit] Complexity

Given N = ranges::distance(first, last), performs O(log N) applications of the predicate pred and projection proj.

However, if sentinels don't model std::sized_sentinel_for<I>, the number of iterator increments is O(N).

[edit] Notes

This algorithm is a more general form of ranges::lower_bound, which can be expressed in terms of ranges::partition_point with the predicate [&](auto const& e) { return std::invoke(pred, e, value); });.

[edit] Example

#include <algorithm>
#include <array>
#include <iostream>
#include <iterator>
 
auto print_seq = [](auto rem, auto first, auto last)
{
    for (std::cout << rem; first != last; std::cout << *first++ << ' ') {}
    std::cout << '\n';
};
 
int main()
{
    std::array v {1, 2, 3, 4, 5, 6, 7, 8, 9};
 
    auto is_even = [](int i) { return i % 2 == 0; };
 
    std::ranges::partition(v, is_even);
    print_seq("After partitioning, v: ", v.cbegin(), v.cend());
 
    const auto pp = std::ranges::partition_point(v, is_even);
    const auto i = std::ranges::distance(v.cbegin(), pp);
    std::cout << "Partition point is at " << i << "; v[" << i << "] = " << *pp << '\n';
 
    print_seq("First partition (all even elements): ", v.cbegin(), pp);
    print_seq("Second partition (all odd elements): ", pp, v.cend());
}

Possible output:

After partitioning, v: 2 4 6 8 5 3 7 1 9
Partition point is at 4; v[4] = 5
First partition (all even elements): 2 4 6 8
Second partition (all odd elements): 5 3 7 1 9

[edit] See also

checks whether a range is sorted into ascending order
(niebloid)[edit]
returns an iterator to the first element not less than the given value
(niebloid)[edit]
locates the partition point of a partitioned range
(function template) [edit]