Step/Stride Iterator与std :: minmax_element一起使用

Raj*_*pta 3 c++ boost stl

我有一个浮点数组,表示浮点值的am*n(行和列)表.我的要求是为每行和每列找到最小/最大元素.对于行,我可以通过指定n个元素的范围使用std :: minmax_element来轻松完成.但是对于列我需要使用步长迭代器,因为放置的元素不是连续的,而是以n的步长间隔放置.是否可以使用boost/STL中的标准迭代器.另一种选择是编写我自己的版本.什么是最好的课程?

Ami*_*ory 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;
}
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

请注意以下事项:

  1. 范围可以由一对迭代器定义,所以我在这里使用它虽然可以使用更简单的形式(它适合堆分配的C风格数组的用例).

  2. 不幸的是,这个子库似乎没有min-max(或者至少我找不到它),所以有两个调用,一个用于min,一个用于max.


给定一个随机访问迭代器,构建一个跨步的前锋并不是很困难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;
};
Run Code Online (Sandbox Code Playgroud)

这应该足够了std::minmax_element.(加一点的逻辑,中decrementadvance成员,以及更改标签,将它做成一个随机访问迭代器了.)

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;
}
Run Code Online (Sandbox Code Playgroud)