C++ Coding Reference: is_sorted_until() and is_sorted()
- 时间:2020-09-17 14:37:27
- 分类:网络文摘
- 阅读:136 次
We talked about sorting (unstable and stable) algorithms implemented in C++ STL. The STL algorithm header also provides the is_sorted_until() and is_sorted() which returns the first out-of-order element in iterator, and whether the container e.g. vector is sorted or not.
C++ is_sorted(): Test whether the container is sorted (in-order)
One easy implementation of the is_sorted() algorithm would be to do a linear scan and compare the current element and its next at a time, return false once it is out-of-order. Return true at the end.
1 2 3 4 5 6 7 8 9 | template <class T> bool isSorted(const vector<T>& arr) { for (int i = 0; i < arr.size() - 1; ++i) { if (arr[i] > arr[i + 1]) { return false; } } return true; } |
template <class T>
bool isSorted(const vector<T>& arr) {
for (int i = 0; i < arr.size() - 1; ++i) {
if (arr[i] > arr[i + 1]) {
return false;
}
}
return true;
}The algorithm runs at O(N), and it is straightforward to use, like this:
1 2 | vector<int> nums({ 1, 2, 3, 4, 5}); isSorted<int>(nums); // true |
vector<int> nums({ 1, 2, 3, 4, 5});
isSorted<int>(nums); // trueTo avoid re-inventing the wheel, we can use std::is_sorted() function from the C++ algorithm package. For example:
1 2 | vector<int> nums({ 1, 2, 3, 4, 5}); std::is_sorted(begin(nums), end(nums)); // true |
vector<int> nums({ 1, 2, 3, 4, 5});
std::is_sorted(begin(nums), end(nums)); // trueAs you probably notice, the std::is_sorted() takes two necessary parameters – which are the iterators pointing to the start of the container and the one-position-beyond-the-end of the container. std::is_sorted() also takes an optional third parameter, which specifies the predicate function that can be used to test if two elements are in-order or not. For example, to check if the array is in reverse order, we can do this:
1 2 3 4 | vector<int> nums({ 1, 2, 3, 4, 5}); std::is_sorted(begin(nums), end(nums), [](auto &a, auto &b) { return a > b; }); // true |
vector<int> nums({ 1, 2, 3, 4, 5});
std::is_sorted(begin(nums), end(nums), [](auto &a, auto &b) {
return a > b;
}); // trueAlternatively, we can pass the reverse iterators rbegin() and rend().
If we look at the template definitions of std::is_sorted() in the algorithm header, we will notice that std::is_sorted() is based on std::is_sorted_until() which will be detailed in the next section.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | template<class _FwdIt, class _Pr> _NODISCARD inline bool is_sorted(_FwdIt _First, _FwdIt _Last, _Pr _Pred) { // test if range is ordered by predicate _Adl_verify_range(_First, _Last); const auto _UFirst = _Get_unwrapped(_First); const auto _ULast = _Get_unwrapped(_Last); return (_STD is_sorted_until(_UFirst, _ULast, _Pass_fn(_Pred)) == _ULast); } template<class _FwdIt> _NODISCARD inline bool is_sorted(_FwdIt _First, _FwdIt _Last) { // test if range is ordered by operator< return (_STD is_sorted(_First, _Last, less<>())); } #if _HAS_CXX17 template<class _ExPo, class _FwdIt, class _Pr, _Enable_if_execution_policy_t<_ExPo> = 0> _NODISCARD inline bool is_sorted(_ExPo&&, _FwdIt _First, _FwdIt _Last, _Pr _Pred) noexcept { // test if range is ordered by predicate // not parallelized at present, parallelism expected to be feasible in a future release return (_STD is_sorted(_First, _Last, _Pass_fn(_Pred))); } template<class _ExPo, class _FwdIt, _Enable_if_execution_policy_t<_ExPo> = 0> _NODISCARD inline bool is_sorted(_ExPo&&, _FwdIt _First, _FwdIt _Last) noexcept { // test if range is ordered by operator< // not parallelized at present, parallelism expected to be feasible in a future release return (_STD is_sorted(_First, _Last)); } #endif /* _HAS_CXX17 */ |
template<class _FwdIt,
class _Pr>
_NODISCARD inline bool is_sorted(_FwdIt _First, _FwdIt _Last, _Pr _Pred)
{ // test if range is ordered by predicate
_Adl_verify_range(_First, _Last);
const auto _UFirst = _Get_unwrapped(_First);
const auto _ULast = _Get_unwrapped(_Last);
return (_STD is_sorted_until(_UFirst, _ULast, _Pass_fn(_Pred)) == _ULast);
}
template<class _FwdIt>
_NODISCARD inline bool is_sorted(_FwdIt _First, _FwdIt _Last)
{ // test if range is ordered by operator<
return (_STD is_sorted(_First, _Last, less<>()));
}
#if _HAS_CXX17
template<class _ExPo,
class _FwdIt,
class _Pr,
_Enable_if_execution_policy_t<_ExPo> = 0>
_NODISCARD inline bool is_sorted(_ExPo&&, _FwdIt _First, _FwdIt _Last, _Pr _Pred) noexcept
{ // test if range is ordered by predicate
// not parallelized at present, parallelism expected to be feasible in a future release
return (_STD is_sorted(_First, _Last, _Pass_fn(_Pred)));
}
template<class _ExPo,
class _FwdIt,
_Enable_if_execution_policy_t<_ExPo> = 0>
_NODISCARD inline bool is_sorted(_ExPo&&, _FwdIt _First, _FwdIt _Last) noexcept
{ // test if range is ordered by operator<
// not parallelized at present, parallelism expected to be feasible in a future release
return (_STD is_sorted(_First, _Last));
}
#endif /* _HAS_CXX17 */C++ is_sorted_until(): Find out the first element that is out of order
The std::is_sorted_until() has the same function signature as std::is_sorted(). It will return the first iterator that is out-of-order or the end() if the original container is in-order. Therefore, the is_sorted() can be simply calling is_sorted_until() to check if the return iterator is end() – beyond the last element of the array/vector.
In the following example, 7 is the first number that is out of order.
1 2 | vector<int> nums({ 1, 2, 3, 4, 7, 5}); auto n = std::is_sorted_until(begin(nums), end(nums)); |
vector<int> nums({ 1, 2, 3, 4, 7, 5});
auto n = std::is_sorted_until(begin(nums), end(nums));Then, iterator n will be pointing to 7 – if we de-reference it using *n we will get 7. Remember to check if the returned iterator is meaningful before de-reference it.
1 2 3 | if (n != end(nums)) { // do something with *n } |
if (n != end(nums)) {
// do something with *n
}In algorithm header, the std::is_sorted_until() have some overloaded function signatures – all supporting the generics using template definitions.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | // FUNCTION TEMPLATES is_sorted AND is_sorted_until template<class _FwdIt, class _Pr> _NODISCARD inline _FwdIt is_sorted_until(const _FwdIt _First, _FwdIt _Last, _Pr _Pred) { // find extent of range that is ordered by predicate _Adl_verify_range(_First, _Last); auto _UFirst = _Get_unwrapped(_First); auto _ULast = _Get_unwrapped(_Last); if (_UFirst != _ULast) { for (auto _UNext = _UFirst; ++_UNext != _ULast; ++_UFirst) { if (_DEBUG_LT_PRED(_Pred, *_UNext, *_UFirst)) { _ULast = _UNext; break; } } } _Seek_wrapped(_Last, _ULast); return (_Last); } template<class _FwdIt> _NODISCARD inline _FwdIt is_sorted_until(_FwdIt _First, _FwdIt _Last) { // find extent of range that is ordered by operator< return (_STD is_sorted_until(_First, _Last, less<>())); } #if _HAS_CXX17 template<class _ExPo, class _FwdIt, class _Pr, _Enable_if_execution_policy_t<_ExPo> = 0> _NODISCARD inline _FwdIt is_sorted_until(_ExPo&&, const _FwdIt _First, _FwdIt _Last, _Pr _Pred) noexcept { // find extent of range that is ordered by predicate // not parallelized at present, parallelism expected to be feasible in a future release return (_STD is_sorted_until(_First, _Last, _Pass_fn(_Pred))); } template<class _ExPo, class _FwdIt, _Enable_if_execution_policy_t<_ExPo> = 0> _NODISCARD inline _FwdIt is_sorted_until(_ExPo&&, _FwdIt _First, _FwdIt _Last) noexcept { // find extent of range that is ordered by operator< // not parallelized at present, parallelism expected to be feasible in a future release return (_STD is_sorted_until(_First, _Last)); } #endif /* _HAS_CXX17 */ |
// FUNCTION TEMPLATES is_sorted AND is_sorted_until
template<class _FwdIt,
class _Pr>
_NODISCARD inline _FwdIt is_sorted_until(const _FwdIt _First, _FwdIt _Last, _Pr _Pred)
{ // find extent of range that is ordered by predicate
_Adl_verify_range(_First, _Last);
auto _UFirst = _Get_unwrapped(_First);
auto _ULast = _Get_unwrapped(_Last);
if (_UFirst != _ULast)
{
for (auto _UNext = _UFirst; ++_UNext != _ULast; ++_UFirst)
{
if (_DEBUG_LT_PRED(_Pred, *_UNext, *_UFirst))
{
_ULast = _UNext;
break;
}
}
}
_Seek_wrapped(_Last, _ULast);
return (_Last);
}
template<class _FwdIt>
_NODISCARD inline _FwdIt is_sorted_until(_FwdIt _First, _FwdIt _Last)
{ // find extent of range that is ordered by operator<
return (_STD is_sorted_until(_First, _Last, less<>()));
}
#if _HAS_CXX17
template<class _ExPo,
class _FwdIt,
class _Pr,
_Enable_if_execution_policy_t<_ExPo> = 0>
_NODISCARD inline _FwdIt is_sorted_until(_ExPo&&, const _FwdIt _First, _FwdIt _Last, _Pr _Pred) noexcept
{ // find extent of range that is ordered by predicate
// not parallelized at present, parallelism expected to be feasible in a future release
return (_STD is_sorted_until(_First, _Last, _Pass_fn(_Pred)));
}
template<class _ExPo,
class _FwdIt,
_Enable_if_execution_policy_t<_ExPo> = 0>
_NODISCARD inline _FwdIt is_sorted_until(_ExPo&&, _FwdIt _First, _FwdIt _Last) noexcept
{ // find extent of range that is ordered by operator<
// not parallelized at present, parallelism expected to be feasible in a future release
return (_STD is_sorted_until(_First, _Last));
}
#endif /* _HAS_CXX17 */–EOF (The Ultimate Computing & Technology Blog) —
推荐阅读:3 Incredible Landing Pages And What We Can Learn From Them What is Cycle Counting and How to Implement It in Your Retail Bu 4 Reasons Why Your Blog is Struggling to Find an Audience 6 Best Fashion Bloggers for Style Inspiration The Strategy You Need to Write Better Blog Posts Than Your Compe How to Improve Your Blog’s Bounce Rate (and Why You Should) Does Your SME Have A Disaster Recovery Plan? 7 Best SEO Trends Gaining Popularity In 2019 How To Choose The Best Hosting Service For A WordPress Website An Idiot’s Guide to Email Automation for Bloggers
- 评论列表
-
- 添加评论