Difference between revisions of "cpp/algorithm/ranges/is sorted until"
m (E ~) |
m (→Example: +<array>.) |
||
(One intermediate revision by one user 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, std::sentinel_for<I> S, class Proj = std::identity, | template< std::forward_iterator I, std::sentinel_for<I> S, class Proj = std::identity, | ||
std::indirect_strict_weak_order<std::projected<I, Proj>> Comp = ranges::less > | std::indirect_strict_weak_order<std::projected<I, Proj>> Comp = ranges::less > | ||
− | constexpr I is_sorted_until( I first, S last, Comp comp = {}, Proj proj = {} ); | + | constexpr I |
+ | is_sorted_until( I first, S last, Comp comp = {}, Proj proj = {} ); | ||
}} | }} | ||
− | {{dcl | num=2 | since=c++20 |1= | + | {{dcl|num=2|since=c++20|1= |
template< std::forward_range R, class Proj = std::identity, | template< std::forward_range R, class Proj = std::identity, | ||
std::indirect_strict_weak_order< | std::indirect_strict_weak_order< | ||
std::projected<ranges::iterator_t<R>, Proj>> Comp = ranges::less > | std::projected<ranges::iterator_t<R>, Proj>> Comp = ranges::less > | ||
− | + | constexpr ranges::borrowed_iterator_t<R> | |
− | is_sorted_until( R&& r, Comp comp = {}, Proj proj = {} ); | + | is_sorted_until( R&& r, Comp comp = {}, Proj proj = {} ); |
}} | }} | ||
{{dcl end}} | {{dcl end}} | ||
− | Examines the range {{ | + | Examines the range {{range|first|last}} and finds the largest range beginning at {{c|first}} in which the elements are sorted in non-descending order. |
− | A sequence is sorted with respect to a comparator {{ | + | A sequence is sorted with respect to a comparator {{c|comp}} if for any iterator {{tt|it}} pointing to the sequence and any non-negative integer {{tt|n}} such that {{tt|it + n}} is a valid iterator pointing to an element of the sequence, {{c|std::invoke(comp, std::invoke(proj, *(it + n)), std::invoke(proj, *it))}} evaluates to {{c|false}}. |
− | @1@ Elements are compared using the given binary comparison function {{ | + | @1@ Elements are compared using the given binary comparison function {{c|comp}}. |
− | @2@ Same as {{v|1}}, but uses {{ | + | @2@ Same as {{v|1}}, but uses {{c|r}} as the source range, as if using {{c|ranges::begin(r)}} as {{c|first}} and {{c|ranges::end(r)}} as {{c|last}}. |
{{cpp/ranges/niebloid}} | {{cpp/ranges/niebloid}} | ||
Line 29: | Line 30: | ||
===Parameters=== | ===Parameters=== | ||
{{par begin}} | {{par begin}} | ||
− | {{par | first, last | iterator-sentinel defining the range to find its sorted upper bound}} | + | {{par|first, last|iterator-sentinel defining the range to find its sorted upper bound}} |
− | {{par | r | the range to find its sorted upper bound}} | + | {{par|r|the range to find its sorted upper bound}} |
− | {{par | comp | comparison function to apply to the projected elements}} | + | {{par|comp|comparison function 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 upper bound of the largest range beginning at {{ | + | The upper bound of the largest range beginning at {{c|first}} in which the elements are sorted in non-descending order. That is, the last iterator {{tt|it}} for which range {{range|first|it}} is sorted. |
===Complexity=== | ===Complexity=== | ||
− | Linear in the distance between {{ | + | Linear in the distance between {{c|first}} and {{c|last}}. |
===Possible implementation=== | ===Possible implementation=== | ||
{{eq fun | {{eq fun | ||
− | + | |1= | |
− | struct is_sorted_until_fn { | + | struct is_sorted_until_fn |
− | + | { | |
− | + | template<std::forward_iterator I, std::sentinel_for<I> S, class Proj = std::identity, | |
− | + | std::indirect_strict_weak_order<std::projected<I, Proj>> Comp = ranges::less> | |
− | + | constexpr I operator()(I first, S last, Comp comp = {}, Proj proj = {}) const | |
− | + | { | |
− | + | if (first == last) | |
− | + | return first; | |
− | + | for (auto next = first; ++next != last; first = next) | |
− | + | if (std::invoke(comp, std::invoke(proj, *next), std::invoke(proj, *first))) | |
− | + | return next; | |
− | + | ||
− | + | ||
− | + | ||
− | + | ||
− | + | return first; | |
− | + | } | |
− | + | template<ranges::forward_range R, class Proj = std::identity, | |
− | + | std::indirect_strict_weak_order< | |
− | + | std::projected<ranges::iterator_t<R>, Proj>> Comp = ranges::less> | |
− | + | constexpr ranges::borrowed_iterator_t<R> | |
− | + | operator()(R&& r, Comp comp = {}, Proj proj = {}) const | |
− | + | { | |
− | + | return (*this)(ranges::begin(r), ranges::end(r), std::ref(comp), std::ref(proj)); | |
− | + | } | |
− | + | ||
}; | }; | ||
Line 79: | Line 75: | ||
===Notes=== | ===Notes=== | ||
− | {{tt|ranges::is_sorted_until}} returns an iterator equal to {{ | + | {{tt|ranges::is_sorted_until}} returns an iterator equal to {{c|last}} for empty ranges and ranges of length one. |
===Example=== | ===Example=== | ||
{{example | {{example | ||
− | + | |code= | |
− | + | #include <array> | |
#include <algorithm> | #include <algorithm> | ||
#include <iostream> | #include <iostream> | ||
Line 93: | Line 89: | ||
{ | { | ||
std::random_device rd; | std::random_device rd; | ||
− | std::mt19937 g{rd()}; | + | std::mt19937 g {rd()}; |
std::array nums {3, 1, 4, 1, 5, 9}; | std::array nums {3, 1, 4, 1, 5, 9}; | ||
constexpr int min_sorted_size = 4; | constexpr int min_sorted_size = 4; | ||
int sorted_size = 0; | int sorted_size = 0; | ||
− | do { | + | do |
+ | { | ||
std::ranges::shuffle(nums, g); | std::ranges::shuffle(nums, g); | ||
const auto sorted_end = std::ranges::is_sorted_until(nums); | const auto sorted_end = std::ranges::is_sorted_until(nums); | ||
Line 105: | Line 102: | ||
std::ranges::copy(nums, std::ostream_iterator<int>(std::cout, " ")); | std::ranges::copy(nums, std::ostream_iterator<int>(std::cout, " ")); | ||
std::cout << " : " << sorted_size << " leading sorted element(s)\n"; | std::cout << " : " << sorted_size << " leading sorted element(s)\n"; | ||
− | } while (sorted_size < min_sorted_size); | + | } |
+ | while (sorted_size < min_sorted_size); | ||
} | } | ||
− | + | |p=true | |
+ | |output= | ||
4 1 9 5 1 3 : 1 leading sorted element(s) | 4 1 9 5 1 3 : 1 leading sorted element(s) | ||
4 5 9 3 1 1 : 3 leading sorted element(s) | 4 5 9 3 1 1 : 3 leading sorted element(s) | ||
Line 119: | Line 118: | ||
===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/dsc is_sorted_until}} | + | {{dsc inc|cpp/algorithm/dsc is_sorted_until}} |
{{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 15:11, 17 April 2023
Defined in header <algorithm>
|
||
Call signature |
||
template< std::forward_iterator I, std::sentinel_for<I> S, class Proj = std::identity, std::indirect_strict_weak_order<std::projected<I, Proj>> Comp = ranges::less > |
(1) | (since C++20) |
template< std::forward_range R, class Proj = std::identity, std::indirect_strict_weak_order< |
(2) | (since C++20) |
Examines the range [
first,
last)
and finds the largest range beginning at first in which the elements are sorted in non-descending order.
A sequence is sorted with respect to a comparator comp if for any iterator it
pointing to the sequence and any non-negative integer n
such that it + n
is a valid iterator pointing to an element of the sequence, std::invoke(comp, std::invoke(proj, *(it + n)), std::invoke(proj, *it)) evaluates to false.
The function-like entities described on this page are niebloids, that is:
- Explicit template argument lists cannot be specified when calling any of them.
- None of them are visible to argument-dependent lookup.
- When any of them are found by normal unqualified lookup as the name to the left of the function-call operator, argument-dependent lookup is inhibited.
In practice, they may be implemented as function objects, or with special compiler extensions.
Contents |
[edit] Parameters
first, last | - | iterator-sentinel defining the range to find its sorted upper bound |
r | - | the range to find its sorted upper bound |
comp | - | comparison function to apply to the projected elements |
proj | - | projection to apply to the elements |
[edit] Return value
The upper bound of the largest range beginning at first in which the elements are sorted in non-descending order. That is, the last iterator it
for which range [
first,
it)
is sorted.
[edit] Complexity
Linear in the distance between first and last.
[edit] Possible implementation
struct is_sorted_until_fn { template<std::forward_iterator I, std::sentinel_for<I> S, class Proj = std::identity, std::indirect_strict_weak_order<std::projected<I, Proj>> Comp = ranges::less> constexpr I operator()(I first, S last, Comp comp = {}, Proj proj = {}) const { if (first == last) return first; for (auto next = first; ++next != last; first = next) if (std::invoke(comp, std::invoke(proj, *next), std::invoke(proj, *first))) return next; return first; } template<ranges::forward_range R, class Proj = std::identity, std::indirect_strict_weak_order< std::projected<ranges::iterator_t<R>, Proj>> Comp = ranges::less> constexpr ranges::borrowed_iterator_t<R> operator()(R&& r, Comp comp = {}, Proj proj = {}) const { return (*this)(ranges::begin(r), ranges::end(r), std::ref(comp), std::ref(proj)); } }; inline constexpr is_sorted_until_fn is_sorted_until; |
[edit] Notes
ranges::is_sorted_until
returns an iterator equal to last for empty ranges and ranges of length one.
[edit] Example
#include <array> #include <algorithm> #include <iostream> #include <iterator> #include <random> int main() { std::random_device rd; std::mt19937 g {rd()}; std::array nums {3, 1, 4, 1, 5, 9}; constexpr int min_sorted_size = 4; int sorted_size = 0; do { std::ranges::shuffle(nums, g); const auto sorted_end = std::ranges::is_sorted_until(nums); sorted_size = std::ranges::distance(nums.begin(), sorted_end); std::ranges::copy(nums, std::ostream_iterator<int>(std::cout, " ")); std::cout << " : " << sorted_size << " leading sorted element(s)\n"; } while (sorted_size < min_sorted_size); }
Possible output:
4 1 9 5 1 3 : 1 leading sorted element(s) 4 5 9 3 1 1 : 3 leading sorted element(s) 9 3 1 4 5 1 : 1 leading sorted element(s) 1 3 5 4 1 9 : 3 leading sorted element(s) 5 9 1 1 3 4 : 2 leading sorted element(s) 4 9 1 5 1 3 : 2 leading sorted element(s) 1 1 4 9 5 3 : 4 leading sorted element(s)
[edit] See also
(C++20) |
checks whether a range is sorted into ascending order (niebloid) |
(C++11) |
finds the largest sorted subrange (function template) |