2009-11-23 137 views
15

如何为二维矢量(矢量矢量)创建迭代器/ s?二维矢量迭代器

+9

可能被描述的问题的背景更好一点? – UncleBens 2009-11-23 17:12:18

+0

更具体地说:你的2D矢量的声明是什么?你想要迭代什么顺序?你想如何使用迭代器? – 2009-11-23 17:17:26

+0

什么是“2D矢量”? – AnT 2009-11-23 17:40:05

回答

32

虽然你的问题是很清楚,我会假设你的意思是一个二维矢量来表示向量的向量:

vector< vector<int> > vvi; 

然后,你需要使用两个迭代器来遍历它,第一个“行”的迭代器,第二个是“列”的迭代器在“行”:

//assuming you have a "2D" vector vvi (vector of vector of int's) 
vector< vector<int> >::iterator row; 
vector<int>::iterator col; 
for (row = vvi.begin(); row != vvi.end(); row++) { 
    for (col = row->begin(); col != row->end(); col++) { 
     // do stuff ... 
    } 
} 
+0

对不起,我的问题不是很清楚,但这正是我想要的。虽然我得到编译器错误此代码: 无法从'std :: _ Vector_iterator <_Ty,_Alloc>'转换为'int'on for(row = vvi.begin(); row!= vvi.end(); row ++){ – miroslavec 2009-11-23 18:23:25

+5

总是使用预增加操作符。使用矢量时,使用矢量很可能不重要,但这是一个不好的习惯。如果它是++ C而不是C++,生活会更加清晰。 – 2009-11-23 23:48:48

+0

如果列中只有2个元素。一旦我们迭代遍历行,如何访问它们。 – 2016-05-05 04:49:19

0

假设你的意思是一个STL迭代器和一个实现对象的通用二维数组的自定义容器,这是不可能的。 STL迭代器仅支持递增和递减(即“下一个”和“先前”)操作,其中通过2D集合的运动需要四个这样的基元(例如,左/右/上/下等...)。隐喻不匹配。

你想做什么?

0

假设你的意思是向量的向量,你必须std::vector记住,没有建作为迭代器来完成它只支持增量和减量操作向前和向后移动。

2D矢量是一个矩阵,所以你需要两个迭代器类型:行迭代器和列迭代器。行迭代器会向上移动和向下移动矩阵,而列迭代器会移动“左”和“右”。

你必须自己实现这些迭代器类,这不一定是一件微不足道的事。当然,除非你只是想迭代矩阵中的每个插槽,在这种情况下,使用索引变量ij的double for循环就可以正常工作。根据您的需要(您的文章内容有点欠缺),您可能需要使用boost::numeric::ublas::matrix,它是来自Boost线性代数库的矩阵类。这个矩阵类具有内置的行和列迭代器,这使得迭代矩阵通常很容易。

+0

正是我的意思,二维矢量矩阵(现在我知道两个)迭代器。我认为问题是明确的:(......无论如何,我是相当新的向量,我必须在这项工作中使用它们 现在另一个问题是,我发布在上面的评论(格式是狗屎)错误。给第一个(行)迭代器赋值,因为那个类型不匹配 – miroslavec 2009-11-23 18:46:53

5

您可以使用range for语句来遍历二维向量中的所有元素。

vector< vector<int> > vec; 

假设您已经将许多元素push_back到vec中;

for(auto& row:vec){ 
    for(auto& col:row){ 
     //do something using the element col 
    } 
} 
1

另一种方式来解释这个问题是你要在vector<vector<>>例如把它喂for_each()或其他一些算法一维迭代器。

可以是这样做的:

#include <iostream> 

#include <iterator> 
#include <vector> 
#include <algorithm> 

// An iterator over a vector of vectors. 
template<typename T> 
class vv_iterator : public std::iterator<std::bidirectional_iterator_tag, T>{ 
public: 

    static vv_iterator<T> begin(std::vector<std::vector<T>>& vv) { 
    return vv_iterator(&vv, 0, 0); 
    } 
    static vv_iterator<T> end(std::vector<std::vector<T>>& vv) { 
    return vv_iterator(&vv, vv.size(), 0); 
    } 

    vv_iterator() = default; 
    // ++prefix operator 
    vv_iterator& operator++() 
    { 
    // If we haven't reached the end of this sub-vector. 
    if (idxInner + 1 < (*vv)[idxOuter].size()) 
    { 
     // Go to the next element. 
     ++idxInner; 
    } 
    else 
    { 
     // Otherwise skip to the next sub-vector, and keep skipping over empty 
     // ones until we reach a non-empty one or the end. 
     do 
     { 
     ++idxOuter; 
     } while (idxOuter < (*vv).size() && (*vv)[idxOuter].empty()); 

     // Go to the start of this vector. 
     idxInner = 0; 
    } 
    return *this; 
    } 
    // --prefix operator 
    vv_iterator& operator--() 
    { 
    // If we haven't reached the start of this sub-vector. 
    if (idxInner > 0) 
    { 
     // Go to the previous element. 
     --idxInner; 
    } 
    else 
    { 
     // Otherwise skip to the previous sub-vector, and keep skipping over empty 
     // ones until we reach a non-empty one. 
     do 
     { 
     --idxOuter; 
     } while ((*vv)[idxOuter].empty()); 

     // Go to the end of this vector. 
     idxInner = (*vv)[idxOuter].size() - 1; 
    } 
    return *this; 
    } 
    // postfix++ operator 
    vv_iterator operator++(int) 
    { 
    T retval = *this; 
    ++(*this); 
    return retval; 
    } 
    // postfix-- operator 
    vv_iterator operator--(int) 
    { 
    T retval = *this; 
    --(*this); 
    return retval; 
    } 
    bool operator==(const vv_iterator& other) const 
    { 
    return other.vv == vv && other.idxOuter == idxOuter && other.idxInner == idxInner; 
    } 
    bool operator!=(const vv_iterator &other) const 
    { 
    return !(*this == other); 
    } 
    const T& operator*() const 
    { 
    return *this; 
    } 
    T& operator*() 
    { 
    return (*vv)[idxOuter][idxInner]; 
    } 
    const T& operator->() const 
    { 
    return *this; 
    } 
    T& operator->() 
    { 
    return *this; 
    } 

private: 
    vv_iterator(std::vector<std::vector<T>>* _vv, 
       std::size_t _idxOuter, 
       std::size_t _idxInner) 
    : vv(_vv), idxOuter(_idxOuter), idxInner(_idxInner) {} 

    std::vector<std::vector<int>>* vv = nullptr; 
    std::size_t idxOuter = 0; 
    std::size_t idxInner = 0; 
}; 



int main() 
{ 
    std::vector<std::vector<int>> a = {{3, 5, 2, 6}, {-1, -4, -3, -5}, {100}, {-100}}; 
    std::reverse(vv_iterator<int>::begin(a), vv_iterator<int>::end(a)); 
    for (const auto& v : a) 
    { 
     std::cout << "{ "; 
     for (auto i : v) 
      std::cout << i << " "; 
     std::cout << "}\n"; 
    } 
} 

打印:

{ -100 100 -5 -3 } 
{ -4 -1 6 2 } 
{ 5 } 
{ 3 } 

注意,因为这需要一个随机访问迭代器,这将不会std::sort()工作。您可以将其设置为随机访问迭代器,但您必须在开始时扫描矢量,以便在固定时间内从平面索引映射到idxOuteridxInner。不是完全无足轻重,但也不难。

+0

我正在寻找你对这个问题的解释。我是对的,这只是非const迭代器,需要为第一个'const_iterator'?是否有任何特定的原因存储索引而不是矢量迭代器?顺便说一句,我花了一段时间来理解这个例子,因为输出使用了“正常”迭代器,而1D迭代器的使用有点隐藏在这个无辜的'reverse'行中 – user463035818 2018-02-01 14:15:34

+0

是的,在我的实际代码中,我有一个'const_iterator'版本,它或多或少是一个非const成员的复制/粘贴(我无法找到避免复制/ PAS TE)。好点我猜没有理由不使用矢量迭代器。这可能更好,我只是没有想到它。 – Timmmm 2018-02-01 20:15:12