Итератор для 2d-вектора

Как создать итератор для sd-вектора (вектор векторов)?

Ответы

Ответ 1

Хотя ваш вопрос не очень ясен, я собираюсь предположить, что вы имеете в виду, что 2D-вектор означает вектор векторов:

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 ...
    }
}

Ответ 2

Вы можете использовать оператор range для выражения для итерации всех элементов в двумерном векторе.

vector< vector<int> > vec;

И пусть предположим, что вы уже push_back много элементов в vec;

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

Ответ 3

Другой способ интерпретировать этот вопрос состоит в том, что вам нужен 1D-итератор над 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(), потому что для этого требуется итератор с произвольным доступом. Вы можете сделать это итератором с произвольным доступом, но вам придется сканировать вектор в начале, чтобы вы могли отображать от плоского индекса до idxOuter и idxInner в постоянное время. Не совсем тривиально, но не сложно.

Ответ 4

Предполагая, что вы имеете в виду итератор STL, и пользовательский контейнер, который реализует общий 2D-массив объектов, это невозможно. Итераторы STL поддерживают только приращение и уменьшение (т.е. "Следующие" "предыдущие" ) операции, при которых движение через 2D-набор требует четырех таких примитивов (например, влево/вправо/вверх/вниз и т.д.). Метафоры не совпадают.

Что вы пытаетесь сделать?

Ответ 5

Предполагая, что вы имеете в виду вектор векторов, и у вас есть std::vector, нет встроенного способа сделать это, поскольку итераторы поддерживают только операции увеличения и уменьшения для перемещения вперед и назад.

2D-вектор - это матрица, поэтому вам нужны два типа итератора: итератор строк и итератор столбца. Итераторы строк будут перемещать "вверх" и "вниз" по матрице, тогда как итераторы столбцов будут перемещаться "влево" и "вправо".

Вы должны сами реализовать эти классы итераторов, что не обязательно тривиально. Если, конечно, вы просто не хотите перебирать каждый слот в матрице, в этом случае двойной цикл, использующий индексные переменные i и j, будет работать нормально. В зависимости от ваших потребностей (ваш пост здесь немного отсутствует в содержимом), вы можете использовать boost::numeric::ublas::matrix, который является матричным классом из библиотеки линейной алгебры Boost. Этот матричный класс имеет встроенные итераторы строк и столбцов, которые упрощают итерацию по матрице.

Ответ 6

Предположим, у вас есть такой вектор:

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.
  }



Обратите внимание, что способ вызова переменных различен в обоих случаях.