Multi-dimensional vector - c++

How can I create a 2D vector? I know that in 2D array, I can express it like:
a[0][1]=98;
a[0][2]=95;
a[0][3]=99;
a[0][4]=910;
a[1][0]=98;
a[1][1]=989;
a[1][2]=981;
a[1][3]=987;
How can one do this using the C++ STL Vector?

vector<vector<int> > a;
If you want to define the rows and columns,
vector<vector<int> > a{{11, 2, 4}, {4, 5, 6}, {10, 8, -12}};

std::vector< std::vector< int > > a; // as Ari pointed
Using this for a growing matrix can become complex, as the system will not guarantee that all internal vectors are of the same size. Whenever you grow on the second dimension you will have to explicitly grow all vectors.
// grow twice in the first dimension
a.push_back( vector<int>() );
a.push_back( vector<int>() );
a[0].push_back( 5 ); // a[0].size() == 1, a[1].size()==0
If that is fine with you (it is not really a matrix but a vector of vectors), you should be fine. Else you will need to put extra care to keep the second dimension stable across all the vectors.
If you are planing on a fixed size matrix, then you should consider encapsulating in a class and overriding operator() instead of providing the double array syntax. Read the C++ FAQ regarding this here

std::vector< std::vector<int> > a;
//m * n is the size of the matrix
int m = 2, n = 4;
//Grow rows by m
a.resize(m);
for(int i = 0 ; i < m ; ++i)
{
//Grow Columns by n
a[i].resize(n);
}
//Now you have matrix m*n with default values
//you can use the Matrix, now
a[1][0]=98;
a[1][1]=989;
a[1][2]=981;
a[1][3]=987;
//OR
for(i = 0 ; i < m ; ++i)
{
for(int j = 0 ; j < n ; ++j)
{ //modify matrix
int x = a[i][j];
}
}

If you don't have to use vectors, you may want to try Boost.Multi_array. Here is a link to a short example.

Declaration of a matrix, for example, with 5 rows and 3 columns:
vector<vector<int> > new_matrix(5,vector<int>(3));
Another way of declaration to get the same result as above:
vector<int> Row;
One row of the matrix:
vector<Row> My_matrix;
My_matrix is a vector of rows:
My_matrix new_matrix(5,Row(3));

dribeas' suggestion is really the way to go.
Just to give a reason why you might want to go the operator() route, consider that for instance if your data is sparse you can lay it out differently to save space internally and operator() hides that internal implementation issue from your end user giving you better encapsulation and allowing you to make space or speed improving changes to the internal layout later on without breaking your interface.

Just use the following method to use 2-D vector.
int rows, columns;
// . . .
vector < vector < int > > Matrix(rows, vector< int >(columns,0));
Or
vector < vector < int > > Matrix;
Matrix.assign(rows, vector < int >(columns, 0));
// Do your stuff here...
This will create a Matrix of size rows * columns and initializes it with zeros because we are passing a zero(0) as a second argument in the constructor i.e vector < int > (columns, 0).

As Ari pointed, vector< vector< int>> is the right way to do it.
In addition to that, in such cases I always consider wrapping the inner vector (actually, whatever it represents) in a class, because complex STL structures tend to become clumsy and confusing.

Related

How to push queue into a vector of queues when vector size is not constant? [duplicate]

In some cases only the below line works.Why so?
vector< vector<int>> a(M,N);
This works in every case.
vector< vector<int>> a(M, vector<int> (N));
What's the difference?
std::vector has a fill constructor which creates a vector of n elements and fills with the value specified. a has the type std::vector<std::vector<int>> which means that it is a vector of a vector. Hence your default value to fill the vector is a vector itself, not an int. Therefore the second options is the correct one.
std::vector<std::vector<int>> array_2d(rows, std::vector<int>(cols, 0));
This creates a rows * cols 2D array where each element is 0. The default value is std::vector<int>(cols, 0) which means each row has a vector which has cols number of element, each being 0.
For declaring a 2D vector we have to first define a 1D array of size equal to number of rows of the desired 2D vector.
Let we want to create a vector of k rows and m columns
"vector<vector<int>> track(k);"
This will create a vector of size k. Then use resize method.
for (int i = 0; i < k; i++) {
track[i].resize(m);
In this way you can declare a 2D vector

Iterating 2D and 3D vectors column wise in C++11?

I have a 2D and 3D vector
using namespace std;
vector< vector<int> > vec_2d;
vector<vector<vector<int>>> vec_3d
I know how to iterate 2D vector row-wise using two iterators. The first the iterator of the "rows" and the second the iterators of the "columns" in that "row". Now, I need to iterate over 2D vector such that the first iterator becomes the iterator of the "columns" and the second the iterator of the rows in that "column" i.e. column-wise.
Using iterators, this will be very difficult. I'd say you would probably need to implement your own iterator classes inheriting from std::iterator<random_access_iterator_tag, Type>.
If you don't actually need to use iterators and really have a good reason for wanting to traverse vectors of vectors in such an odd way (and are aware of how this will slow down memory access by preventing caching) then it could easily be done using indexes.
Here's an example using indexes which handles the tricky case where the inner vectors are not all of the same length.
using namespace std;
int main()
{
vector< vector<int> > vec_2d = { {1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10} };
bool is_col_out_of_bounds = false;
for (size_t col=0; ! is_col_out_of_bounds; col++)
{
is_col_out_of_bounds = true;
for (size_t row=0; row<vec_2d.size(); row++)
{
if (col < vec_2d[row].size())
{
is_col_out_of_bounds = false;
cout << vec_2d[row][col] << endl;
}
}
}
return 0;
}
Output:
1
4
8
2
5
9
3
6
10
7
If you want to guarantee that all rows are of the same length, then vector<array<T, N>> may be a better choice.
A simple answer: Who said your layout should be interpreted row-wise? A std::vector<std::vector<Foo>> has no knowledge about rows and columns, so let the outer-most vector represent columns instead of rows.
This is a pain when printing to the terminal, which is likely to do it row-wise, but if column layout is preferred internally, do it that way.

C++ - A 3-d data structure - should I use vector of pointers or vector of vectors?

I have to maintain a data structure which is 3 dimensional. So let us say it's dimensions are :- l x m x n. In the program that I wish to write l and m will be known since the time the data structure is being constructed . But n has to be dynamic throughout runtime. And n may be different for the different vectors in the grid lxm. (Once this structure is created I never intend to destruct it as I will be needing it throughout).
For the moment let us assume it's a 2-dimensional data structure that I wish to make, should I make a vector<vector<int>> or a vector<vector<int>*> ? Also I know how I might initialise the vector to the required size in the first case, i.e I might do something like :-
vector<vector<int> > A(m)
to initialise the size of the outer dimension to m. But in the second case, once I have created a vector of pointers to vectors, how do I create the vectors to which the pointers point.
Carrying this to the 3-d case, should I use ,
a vector<vector<vector>> or a vector<vector<vector*>> or some other combination ?
Please, suggest any changes so that I may reframe the question if it's not framed properly.
You're better using a single vector (and not nested ones), since the memory is guaranteed to be contiguous in this case and your code will be way faster due to no cache misses. In this case, you need to map from 3D (2D) to 1D and vice-versa, but this is pretty straightforward
for 2D:
(x,y) <-> y*DIM_X + x;
for 3D:
(x,y,z) <-> z*(DIM_Y*DIM_X) + y*DIM_X + x;
If you really insist to use nested vectors, you can do something like:
#include <vector>
template<typename T>
using vec = std::vector<T>; // to save some typing
int main()
{
// creates a 5 x 4 x 3 vector of vector of vector
vec<vec<vec<double>>> v{5, vec<vec<double>>{4, vec<double>{3}}};
}
EDIT
Responding to your latest edit: use
std::vector<std::vector<double>> v{DIM_X*DIM_Y, std::vector<double>};
// address (x,y,z)
v[y*DIM_X+x, z] = val_x_y_z;
If you further happen to know the dimensions of the inner vectors, you can preallocate memory for them using std::vector::reserve. This will speed things up since there won't be any (slow) re-allocations.
No, use a proper multidimensional array: Boost MultiArray http://www.boost.org/doc/libs/1_59_0/libs/multi_array/doc/user.html
#include "boost/multi_array.hpp"
int main () {
// Create a 3D array that is 3 x 4 x 2
typedef boost::multi_array<int, 3> array_type;
typedef array_type::index index;
array_type A(boost::extents[3][4][2]);
// Assign values to the elements
int values = 0;
for(index i = 0; i != 3; ++i)
for(index j = 0; j != 4; ++j)
for(index k = 0; k != 2; ++k)
A[i][j][k] = values++;
}

Problems using 3-dimensional vector

How can I work with a 3 dimensional vector in C++?
vector<vector<vector<int> > > vec (1,vector<vector<int> >(1,vector <int>(1,12)));
When I try something like this
cout << vec[0][0][0]; vec[0][0][1] = 13;
everything works just fine.
The problem is that I can only change the last elements. If I try accessing the first and second element, like this
vec[0][1][0] = 13;
or this
vec.push_back(vector<vector<int > >());
vec[0].push_back(vector<int>());
v[1][0].push_back(13);
my program crashes.
How can I add and access elements in a 3d vector?
I would never do vector<vector<vector<int> > > as in this way you have many allocations what could be expensive. I would simply use vector<int> with smart indexing (e.g.: see below). If you will work with double based matrices, in this way intel MKL or any other BLAS library easily could be used.
Its price is increased complexity when matrix sizes are changed, but you could win many in performance.
Useful link: C++ FAQ.
static int const M = 16;
static int const N = 16;
static int const P = 16;
inline int& set_elem(vector<int>& m_, size_t i_, size_t j_, size_t k_)
{
// you could check indexes here e.g.: assert in debug mode
return m_[i_*N*P + j_*P + k_];
}
inline const int& get_elem(const vector<int>& m_, size_t i_, size_t j_, size_t k_)
{
// you could check indexes here e.g.: assert in debug mode
return m_[i_*N*P + j_*P + k_];
}
vector<int> matrix(M*N*P, 0);
set_elem(matrix, 0, 0, 1) = 5;
vector<vector<vector<int> > > vec (1,vector<vector<int> >(1,vector <int>(1,12)));
cout << vec[0][0][0]; vec[0][0][1] = 13;
evething is OK.
You are mistaken. Everything is not OK. The vector vec[0][0] has only one element and thus vec[0][0][1] is out of bounds and therefore the assignment has undefined behaviour. You have the same problem with vec[0][1][0] = 13; and v[1][0].push_back(13)
You can fix that by accessing only indices that exist in your vectors. If you want more than one element, then either construct the vectors with more elements initially, or push them after construction.
At the begining I have 1x1x1 vector. So how can I push elements. using push_back() ? For example I have 1x1x1 and I want to add v[1][1][0] = 2 ?
If you for some reason want to start with 1x1x1 vector of vectors of vectors of ints and want to access v[1][1][0], here is example code to add the v[1][1][0] element with minimal changes to the original vector:
// vector of ints that contains one element, 2
// this will vector eventually be the v[1][1] and the integer element will be v[1][1][0]
// since we initialize the integer as 2, there's no need to assign it later though
vector<int> vi(1, 2);
// vector of vectors that contains one default constructed vector
// vvi will eventually be the v[1] element and the default constructed vector will be v[1][0]
vector<vector<int>> vvi(1);
// push vi into vvi, making it vvi[1] and eventually v[1][1]
vvi.push_back(vi);
// push vvi into v, making it v[1]
v.push_back(vvi);
What you have,
vector<vector<vector<int> > > vec (1,vector<vector<int> >(1,vector <int>(1,12)));
creates 1 x 1 x 1 matrix with the value of the only element set to 12.
To create something that is analogous to a M x N x P matrix, you need to use:
vector<vector<vector<int> > > vec (M,vector<vector<int> >(N,vector <int>(P,x)));
That will create an M x N x P matrix with the value of each element set to x.

Declaring a 2D vector

In some cases only the below line works.Why so?
vector< vector<int>> a(M,N);
This works in every case.
vector< vector<int>> a(M, vector<int> (N));
What's the difference?
std::vector has a fill constructor which creates a vector of n elements and fills with the value specified. a has the type std::vector<std::vector<int>> which means that it is a vector of a vector. Hence your default value to fill the vector is a vector itself, not an int. Therefore the second options is the correct one.
std::vector<std::vector<int>> array_2d(rows, std::vector<int>(cols, 0));
This creates a rows * cols 2D array where each element is 0. The default value is std::vector<int>(cols, 0) which means each row has a vector which has cols number of element, each being 0.
For declaring a 2D vector we have to first define a 1D array of size equal to number of rows of the desired 2D vector.
Let we want to create a vector of k rows and m columns
"vector<vector<int>> track(k);"
This will create a vector of size k. Then use resize method.
for (int i = 0; i < k; i++) {
track[i].resize(m);
In this way you can declare a 2D vector