我有一个浮点数组,表示浮点值的m * n(行和列)表。我的要求是为每行和每列找到最小/最大元素。对于行,我可以通过指定n个元素的范围使用std :: minmax_element来轻松完成。但是对于列我需要使用步长迭代器,因为放置的元素不是连续的,而是以n的步长间隔放置。是否可以使用boost / STL中的标准迭代器。另一种选择是编写我自己的版本。 什么是最好的课程?
答案 0 :(得分:8)
执行此操作的两种方式(使用range-v3
(或boost::range
)和boost::iterator
。
使用range-v3
,立即:
#include <iostream>
#include <range/v3/all.hpp>
using namespace ranges;
int main() {
std::vector<std::size_t> src{1, 2, 3, 4, 5, 6, 7};
const auto min_max = minmax(src | view::stride(3));
std::cout << min_max.first << " " << min_max.second << std::endl;
}
在boost::range
中,使用boost::adaptors::strided
。
#include <boost/range/adaptor/strided.hpp>
#include <boost/range/algorithm/copy.hpp>
#include <boost/assign.hpp>
#include <boost/range/algorithm.hpp>
#include <algorithm>
#include <iostream>
#include <vector>
int main()
{
using namespace boost::adaptors;
using namespace boost::assign;
std::vector<int> input;
int arr[] = {1, 2, 3, 4, 5, 6, 7};
auto str = std::make_pair(&arr[0], &arr[8]) | strided(3);
std::cout << *boost::range::min_element(str) << " " << *boost::range::max_element(str) << std::endl;
}
请注意以下事项:
范围可以由一对迭代器定义,所以我在这里使用了它,虽然可以使用更简单的形式(它适合堆分配的C风格数组的用例)。
不幸的是,这个子库似乎没有min-max(或者至少我找不到它),所以有两个调用,一个用于min,一个用于最大
给定一个随机访问迭代器,构建一个跨步前进boost::iterator_facade
并不是很困难:
#include <iostream>
#include <vector>
#include <iterator>
#include <cstddef>
#include <algorithm>
#include <boost/iterator/iterator_facade.hpp>
template<typename It>
class stride_iterator :
public boost::iterator_facade<
stride_iterator<It>,
typename std::iterator_traits<It>::value_type,
boost::forward_traversal_tag> {
public:
stride_iterator() = default;
stride_iterator(It it, It end_it, std::size_t stride) :
m_it{it}, m_end_it{end_it}, m_stride{stride}
{}
private:
friend class boost::iterator_core_access;
void increment() {
if(std::distance(m_it, m_end_it) < m_stride) {
m_it = m_end_it;
return;
}
std::advance(m_it, m_stride);
}
bool equal(const stride_iterator<It> &other) const {
return m_it == other.m_it;
}
typename std::iterator_traits<It>::value_type &dereference() const {
return *m_it; }
It m_it, m_end_it;
std::size_t m_stride;
};
这对std::minmax_element
来说应该足够了。 (添加一些逻辑,decrement
和advance
成员,以及更改标记,也会使其成为随机访问迭代器。)
int main() {
using vec_t = std::vector<int>;
vec_t v{1, 2, 3, 4, 5, 6, 7};
stride_iterator<vec_t::iterator> b{std::begin(v), std::end(v), 3}, e{std::end(v), std::end(v), 3};
auto min_max = std::minmax_element(b, e);
std::cout << *min_max.first << " " << *min_max.second << std::endl;
}