要查找大于基数的第一个std::find_if
元素,您可以尝试使用lambda 谓词,如果指向的当前元素大于基迭代器指向的元素,则返回 true。由于 lambda 不幸不是多态的,因此您需要使用指定类型std::iterator_traits
(以便它也适用于指针)。
要找到大于基数的最小元素,您需要进行线性扫描,重复查找剩余列表中大于基数的第一个元素,然后检查它是否小于当前最小值。每次更新最小值时,也会将迭代器增加到当前最小值,这样您只需在剩余部分中寻找下一个候选者。这使得这个算法O(N)
在元素的数量上N
。
#include <algorithm>
#include <array>
#include <iostream>
#include <iterator>
template<typename FwdIt>
FwdIt first_larger(FwdIt first, FwdIt last, FwdIt base)
{
typedef typename std::iterator_traits<FwdIt>::value_type T;
return std::find_if(first, last, [=](T const& elem) {
return elem > *base;
});
}
template<typename FwdIt>
FwdIt first_larger(FwdIt first, FwdIt last)
{
return first_larger(first, last, first);
}
template<typename FwdIt>
FwdIt min_larger(FwdIt first, FwdIt last)
{
typedef typename std::iterator_traits<FwdIt>::value_type T;
auto min = last;
auto found = false;
for(auto it = first; it != last; ++it) {
auto m = first_larger(it, last, first);
if (m == last) break;
it = min = m;
found = true;
}
return found? min : last;
}
int main()
{
std::array<int,11> arr = {{ 54, 314, 5, 7, 1, -1, 0, 14, 9, 8, 6 }};
auto b = &arr[3];
auto f = first_larger(b, arr.end());
auto m = min_larger(b, arr.end());
std::cout << *b << "\n"; // 7
if(f != arr.end()) std::cout << *f << "\n"; // 14
if(m != arr.end()) std::cout << *m << "\n"; // 8
return 0;
}
您可能可以将其概括为一个函数
template<typename FwdIt, typename Pred, typename Cmp>
FwdIt min_element_if(FwdIt first, FwdIt last, Pred pred, Cmp cmp)
{
// return iterator to smallest element satisfying Predicate
}
和其他设置Cmp
等于等的重载operator<
。不幸的是,STL 不包含更基本算法的这种组合。您可以查看Boost.Iterator以使用过滤器适配器
// equivalent to min_element_if(first, last, pred)
min_element(boost::make_filter_iterator(first, last, pred),
boost::make_filter_iterator(last, last, pred));