2009-11-23 10 views
15

Cómo crear iterador/es para el vector 2d (un vector de vectores)?iterador para el vector 2d

+9

¿Puede describir el contexto de la pregunta un poco mejor? – UncleBens

+0

Más específicamente: ¿cuál es la declaración de su vector 2d? ¿Qué orden quieres iterar? ¿Cómo quieres usar el iterador? –

+0

¿Qué es "2d vector" ??? – AnT

Respuesta

32

Aunque su pregunta es no muy clara, voy a asumir que quiere decir un vector 2D en el sentido de un vector de vectores:

vector< vector<int> > vvi; 

Luego hay que utilizar dos iteradores para atravesarlo, la primera el iterador de las "filas", el segundo de los iteradores de las "columnas" en el que "fila":

//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

Lamento que mi pregunta no fuera tan clara, pero esto es exactamente lo que quería. Aunque obtengo un error de compilación con este código: no se puede convertir de 'std :: _ Vector_iterator <_Ty,_Alloc>' a 'int' en (fila = vvi.begin(); fila! = Vvi.end(); fila ++) { – miroslavec

+5

siempre use operadores de pre incremento. Con los vectores es probable que no importe cuando se usa un vector, pero es un mal hábito entrar. La vida sería mucho más clara si hubiera sido ++ C en lugar de C++. –

+0

Si solo hay 2 elementos en las columnas. Cómo acceder a ellos una vez que iteramos por la fila. –

0

Suponiendo que se refiera a un iterador STL, y un contenedor personalizado que implemente una matriz 2D genérica de objetos, esto es imposible. Los iteradores STL solo admiten operaciones de incremento y decremento (es decir, "siguiente" y "anterior"), donde el movimiento a través de un conjunto 2D requiere cuatro de estas primitivas (por ejemplo, izquierda/derecha/arriba/abajo, etc.). Las metáforas no coinciden.

¿Qué estás tratando de hacer?

0

Asumiendo que significa un vector de vectores, y tiene std::vector en mente, no hay construyeron en forma de hacerlo, como iteradores solo admite operaciones de incremento y decremento para avanzar y retroceder.

Un vector 2D es una matriz, por lo que necesitaría dos tipos de iteradores: un iterador de fila y un iterador de columna. Los iteradores de fila moverían "hacia arriba" y "hacia abajo" la matriz, mientras que los iteradores de columna se moverían "izquierda" y "derecha".

Debe implementar estas clases de iterador usted mismo, lo cual no es necesariamente algo trivial. A menos que, por supuesto, simplemente desee iterar sobre cada ranura en la matriz, en cuyo caso un bucle for for usando las variables de índice i y j funcionará perfectamente. Dependiendo de sus necesidades (su publicación es un poco deficiente en contenido aquí), es posible que desee utilizar boost::numeric::ublas::matrix, que es una clase de matriz de la biblioteca de álgebra lineal Boost. Esta clase de matriz tiene iteradores de fila y columna incorporados, lo que hace que sea más fácil iterar sobre una matriz.

+0

Exactamente lo que quise decir, matriz de vectores 2D con (ahora sé que dos) iteradores. Pensé que las preguntas eran claras :(... de todos modos soy bastante nuevo para los vectores y tengo que usarlos en este trabajo. Ahora otro problema es ese error que publiqué en el comentario anterior (el formateo es una mierda). No puedo asignar valor al primer iterador (fila) porque ese tipo no coincide – miroslavec

5

Puede usar range para la instrucción para iterar todos los elementos en un vector bidimensional.

vector< vector<int> > vec; 

Y supongamos que ya has push_back una gran cantidad de elementos en vec;

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

Otra forma de interpretar esta pregunta es que quieres un iterador 1D durante un vector<vector<>> por ejemplo, para alimentar a for_each() o algún otro algoritmo.

puede hacerlo de esta manera:

#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"; 
    } 
} 

Lienzo:

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

Nota esto no va a trabajar con std::sort() porque eso requiere un iterador de acceso aleatorio. Podría hacer que sea un iterador de acceso aleatorio, pero tendría que escanear el vector al inicio para que pueda mapear desde el índice plano a idxOuter y idxInner en tiempo constante. No es totalmente trivial, pero tampoco es difícil.

+0

Estaba buscando exactamente su interpretación de la pregunta. Estoy en lo correcto, que este es solo el iterador no const y uno necesitaría escribir una segunda clase para el 'const_iterator'? ¿Hay alguna razón específica para almacenar índices en lugar de los iteradores de vectores? Btw me llevó un tiempo entender el ejemplo, porque el resultado utiliza los iteradores" normales ", mientras que el uso del iterador 1D está un poco oculto en esta inocente línea 'reverse' – user463035818

+0

Sí, en mi código real tengo una versión' const_iterator'. Es más o menos una copia/pega con los miembros no const eliminados (no pude encontrar una manera de evitar el copiar/pas te). Buen punto, supongo que no hay una razón para no usar vectores iteradores. Probablemente sea mejor, simplemente no pensé en eso. – Timmmm

Cuestiones relacionadas