2009-11-23 155 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