C++ Coding Reference: is_sorted_until() and is_sorted()
- 时间:2020-09-17 14:37:27
- 分类:网络文摘
- 阅读:100 次
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) —
推荐阅读:转日月经筒,任一帙诗卷成灰 元旦节的迎新活动作文400字 夕阳无限好 除号和比号的由来 直线比射线长吗 小学立体图形公式大全 小学平面图形公式大全 代数式的含义 什么是思维导图 图中有几组互相垂直的线段
- 评论列表
-
- 添加评论