我想要的是:另一个迭代器之后的下一个元素的迭代器(让我们称之为基础迭代器),它比字库迭代器所指向的元素(也就是说,如果我有一个'a')按字典顺序放大(>)其余的是[c,d,a,b]我想要b,或者更确切地说是b)的迭代器。我不知道<算法>可用于此的功能,所以如果您愿意,我会“手动”进行。
我如何思考我能做到:运行这个lambda,在集合上有一些累积:
[mism.first](it_t acc, it_t el)
{
if(*el > *mism.first) {
return iter_min(acc,el);
}
return acc;
}
(iter_min(a,b)是* a< = * b时,mism.first是“base iterator”)。但是由于累积在值而不是迭代器上工作,我不能。迭代器有这样的东西吗?如果没有,你会说我应该写它(我不认为我会用它来过度训练)或者我只是以“错误”的方式去做(顺便说一句,我最终会换掉它)迭代器指向的元素。我知道这听起来很像next_permutation,但是我正在做的事情与排列有很大关系,它不是完全我想要的东西?/ p>
答案 0 :(得分:2)
我看到的最简单的可能性是创建一个可以迭代的范围,包含来自[base, end)
的连续迭代器。使用Boost.Iterators counting_iterator
可以实现这一点,但即使没有提升也应该很容易实现。
你提议的lambda几乎可以按原样运行:
some_iterator base = ..., end = ...;
some_iterator the_next_least_thing =
std::accumulate(boost::make_counting_iterator(base),
boost::make_counting_iterator(end),
end,
[=](some_iterator acc, some_iterator cur) {
return (*cur > *base && (acc == end || *cur < *acc)) ? cur : acc });
答案 1 :(得分:1)
要查找大于基数的第一个元素,可以尝试将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));
答案 2 :(得分:1)
使用find_if,提供迭代器+ 1作为起点:
bool mycomp (char c1, char c2)
{ return lexicographical_compare(*c1,*c1,*c2,*c2); }
vector<char>::iterator nextBigger = find_if(it+1,end,mycomp)