Я знаю, что этот поток старый, но я считаю весьма полезным реализовать мощную функцию argmax в C ++.
Однако, насколько я вижу, все приведенные выше примеры основаны на std ::max_element, который выполняет сравнение между элементами (используя функтор или вызывая оператор <).это может быть медленным, если расчет для каждого элемента стоит дорого.Он хорошо работает для сортировки чисел и обработки простых классов, но что, если функтор намного сложнее?Может быть, вычисление эвристического значения шахматной позиции или чего-то еще, что генерирует огромное дерево и т. Д. </p>
Реальный argmax, как упоминалось в начале потока, вычислит только один аргумент arg, а затем сохранит его для сравнения сдругие.
РЕДАКТИРОВАТЬ: Хорошо, я был раздражен и имел слишком много свободного времени, поэтому я создал одну версию
#include <iostream>
#include <algorithm>
#include <iterator>
#include <vector>
template<typename IteratorT, typename HeuristicFunctorT>
IteratorT argmax(IteratorT && it, const IteratorT & end, const HeuristicFunctorT & functor) {
IteratorT best(it++);
typename HeuristicFunctorT::result_type best_value(functor(*best));
for(; it != end; ++it) {
typename HeuristicFunctorT::result_type value(functor(*it));
if (value > best_value) {
best_value = value;
best = it;
}
}
return best;
}
template<typename IteratorT, typename HeuristicFunctorT>
inline IteratorT argmax(const IteratorT & begin, const IteratorT & end, const HeuristicFunctorT & functor) {
return argmax(IteratorT(begin), end, functor);
}
class IntPairFunctor : public std::unary_function< std::pair<int, int>, int > {
public:
int operator() (const std::pair<int, int> & v) const {
return v.first + v.second;
}
};
std::pair<int, int> rand_pair() {
return std::make_pair(rand(), rand());
}
int main(int argc, const char **argv) {
srand(time(NULL));
std::vector< std::pair<int, int> > ints;
std::generate_n(std::back_insert_iterator< std::vector< std::pair<int, int> > >(ints), 1000, rand_pair);
std::vector< std::pair<int, int> >::iterator m (argmax(ints.begin(), ints.end(), IntPairFunctor()));
std::cout << std::endl << "argmax: " << *m << std::endl;
}
Версия без C ++ 11 намного проще, только шаблон:
template<typename IteratorT, typename HeuristicFunctorT>
IteratorT argmax(IteratorT it, const IteratorT & end, const HeuristicFunctorT & functor) {
IteratorT best(it++);
typename HeuristicFunctorT::result_type best_value(functor(*best));
for(; it != end; ++it) {
typename HeuristicFunctorT::result_type value(functor(*it));
if (value > best_value) {
best_value = value;
best = it;
}
}
return best;
}
Обратите внимание, что ни в одной версии не требуются аргументы шаблона, единственное требование - эвристическийреализует класс unary_function