2Dベクトル(ベクトルのベクトル)のイテレータを作成するにはどうすればよいですか?
あなたの質問はnotで非常に明確ですが、2Dベクトルを意味するものとして、ベクトルのベクトルを意味すると仮定します。
vector< vector<int> > vvi;
次に、2つのイテレータを使用してトラバースする必要があります。1つ目は「行」のイテレータ、2つ目はその「行」の「列」のイテレータです。
//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 ...
}
}
Range forステートメントを使用して、2次元ベクトルのすべての要素を繰り返すことができます。
vector< vector<int> > vec;
そして、あなたはすでにvecに多くの要素をPush_backしていると仮定しましょう。
for(auto& row:vec){
for(auto& col:row){
//do something using the element col
}
}
この質問を解釈する別の方法は、_vector<vector<>>
_に対する1Dイテレータを使用して、たとえば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()
では機能しません。ランダムアクセスイテレータが必要なためです。ランダムアクセスイテレータにすることもできますが、フラットインデックスからidxOuter
およびidxInner
に一定の時間でマッピングできるように、最初にベクトルをスキャンする必要があります。完全に取るに足らないことではありませんが、難しくもありません。
次のようなベクトルがあるとします。vector <vector<int>> vect{{1,2,3},{4,5,6},{7,8,9}};
2Dベクトルでイテレータを使用するようになりました:-
for(auto i = vect.begin() ; i<vect.end() ; i++)
{
for(auto j = i->begin() ; j<i->end() ; j++)
cout << *j <<" ";
cout <<"\n";
//similarly you can do other things
}
また、他の短い方法は
for(auto i : vect)
{
for(auto j : i)
cout << j <<" ";
cout << "\n";
//similarly you can do other things also.
}
変数の呼び出し方法はどちらの場合も異なることに注意してください。
イテレータがサポートするのはインクリメントとデクリメントの操作だけなので、ベクトルのベクトルを意味し、std::vector
を念頭に置いている場合、組み込みの方法はありません。
2Dベクトルは行列なので、行イテレーターと列イテレーターの2種類のイテレーターが必要になります。行反復子は行列を「上」および「下」に移動し、列反復子は「左」および「右」に移動します。
これらのイテレータクラスを自分で実装する必要がありますが、これは必ずしも簡単なことではありません。もちろん、単にマトリックスの各スロットを反復処理したい場合を除き、この場合、インデックス変数i
およびj
を使用したdouble forループは問題なく機能します。必要に応じて(投稿の内容が少し不足しています)、Boost線形代数ライブラリの行列クラスであるboost::numeric::ublas::matrix
を使用できます。この行列クラスには、行と列の反復子が組み込まれているため、一般的に行列の反復が簡単になります。
このような場合にはautoキーワードを使用できます。
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
int main() {
// your code goes here
vector<vector<int>>v;
for(int i=0;i<5;i++)
{
vector<int> x={1,2,3,4,5};
v.Push_back(x);
}
cout<<"-------------------------------------------"<<endl;
cout<<"Print without iterator"<<endl;
cout<<"-------------------------------------------"<<endl;
for(int i=0;i<5;i++)
{
vector<int> y=v[i];
for(int j=0;j<y.size();j++)
{
cout<<y[j]<<" ";
}
cout<<endl;
}
cout<<"-------------------------------------------"<<endl;
cout<<"Print with iterator"<<endl;
cout<<"-------------------------------------------"<<endl;
for(auto iterator=v.begin();iterator!=v.end();iterator++)
{
vector<int> y=*iterator;
for(auto itr=y.begin();itr!=y.end();itr++)
{
cout<<*itr<<" ";
}
cout<<endl;
}
return 0;
}
STLイテレーターと、オブジェクトの一般的な2D配列を実装するカスタムコンテナーを意味すると想定すると、これは不可能です。 STLイテレータは、インクリメントおよびデクリメント(つまり、「次の」「前の」)操作のみをサポートします。2Dセットを通過するモーションには、4つのプリミティブ(左/右/上/下など)が必要です。比喩は一致しません。
あなたは何をしようとしているのですか?