Initialization of vector of vectors - c++

vector<vector<int>>dp(3);
for(int i = 0; i<3; i++) {
vector<int>price(10);
dp.push_back(price);
}
It is showing error while initialization. Can anyone explain the reason behind this wrong code?

If what you intend is declaring an empty two dimensional vector[3][10], you can do it at once.
#include <iostream>
#include <vector>
int main()
{
std::vector<std::vector<int>> dp(3,std::vector<int>(10));
std::cout<<dp.size(); //3
std::cout<<std::endl<<dp[0].size(); //10
}
Then you can assign values to it by using something like dp[0][4]=12; or with loops.

This statement
vector<vector<int>>dp(3);
create a vector dp with 3 default constructed int vectors and in loop, you are doing
dp.push_back(price);
the push_back() appends the given vector value to the end of the container. So, after loop, you will end up having dp vector of size 6, out of which first 3 are empty vectors and last 3 are vectors of 10 int elements.
Instead of specifying size, you can use reserve() to reserver the storage:
vector<vector<int>>dp;
dp.reserve(3);
for(int i = 0; i<3; i++) {
vector<int>price(10);
dp.push_back(price); // A suggestion: check emplace_back
}
To create a vector of 3 vectors, each having 10 int elements, you can simply do:
vector<vector<int> >dp (3, vector<int>(10));
Also, if you want to initialise all elements with some value, say -1, you can do:
vector<vector<int> >dp (3, vector<int>(10, -1));

Related

How to calculate the sum of individual elements from two 2D arrays?

I want to write a function addArrays which will, as parameters, take two 2D arrays of type int and of dimensions 3x4, and it's job is to add individual elements of each index from the given arrays and display it in the console.
In main(), I created two 2D arrays arrA and arrB of appropriate sizes with intitialized members and check the functionality of the created function.
My code so far:
#include <iostream>
using namespace std;
void addArrays(int x[3][4], int y[3][4]);
int main()
{
int arrA[3][4] = { {7, 8, 13, 22}, {56, 4, 78, 3}, {22, 13, 46, 5} };
int arrB[3][4] = { {32, 47, 56, 14}, {33, 100, 19, 64}, {4, 18, 157, 84} };
}
void addArrays(int x[3][4], int y[3][4])
{
}
Honestly, I know how to work with 1D arrays, but not displaying the sum of all individual elements. I know I have to use a for loop, but again, I'm confused as to how to pass in a 2D array and use it.
You mention you know how to work with 1D arrays, it's the same for 2D arrays, only with one more dimension.
In a 1D array you use arrA[0] to access the first element of the array, in a 2D array you use arrA[0][0] to access the first element in the first line of the array, arrA[0][1] to access the second element in the first line of the array. To access the first element in the second line you would use arrA[1][0] and so on, you get the idea.
So to loop through all the elements in the array you can use nested loops like so:
void addArrays(int x[3][4], int y[3][4])
{
for( int i = 0; i < 3; i++){ // make sure to use the correct dimensions
for(int j = 0; j < 4; j++){ // 3 lines and 4 columns
// x[i][j] accesses elements in array x
// y[i][j] accesses elements in array y
}
}
}
I think you'll manage to do the math yourself. After that you just need to send data to the standard output, i.e. to print data in the console. For that, as you may know, you use std::cout.
Side notes:
In the function void addArrays(int x[3][4], int y[3][4]){...} you may omit the first dimension of the array i.e. int x[][4] or int (*x)[4] instead of int x[3][4], since the argument will decay to a pointer to array.
Since it seems that you are not to change the values of the passed arrays, using const is recommend. You would have void addArrays(const int (*x)[4], const int (*y)[4]);
As you are using C++, you can take advantage of the possibility of using references, something like void addArrays(const int (&x)[3][4], const int (&y)[3][4]){/*same code*/}, the benefit being you must pass a correct object to the function otherwise the program will fail to compile whereas in the previous versions if you pass, for example, NULL, i.e. addArrays(arrA, NULL); the program will compile fine but will result in undefined behavior when you run it. References are safer and you should use them when possible.
It's more or less consensual among more experienced C++ programmers that the usage of using namespace std; is not a good practice, you can read more about it, and find alternatives following the link.
I will start this for you and try to give you an idea of the general structure, but since you have not shown your attempt at the problem I won't fill things in for you.
The basic idea here when looping through 2D arrays (of size MxN) is that you can really just think about it in terms of looping through M arrays of length N.
void loopThroughArray(int arr[M][N])
{
// Loop over M arrays
for (int m = 0; m < M; ++m) {
// For each m'th array, loop over its N contents
for (int n = 0; n < N; ++n) {
// Doing work
arr[m][n] = 1234;
}
}
}

Create 2D vector from 2 1D vectors

I am fairly new to vectors and I'm trying to populate a 2D vector from 2 1D vectors for coordinate points. I have 2 vectors like this where source_x and source_y contains values from a file:
std::vector<float,T<float>> pos_x(5);
std::vector<float,T<float>> pos_y(5);
for (int i = 0; i < 5 ; i++){
pos_x[i] = i+1; //{1,2,3,4,5}
}
for (int i = 0; i < num ; i++){
pos_y[i] = i+1 ; //{1,2,3,4,5}
}
I created my 2D vector like this:
std::vector<std::vector<float, T<float>>> position;
for (int i = 0; i < num ; i++){
for (int j = 0; j < num ; i++){
//Output expected: {{1,2,3,4,5},{1,2,3,4,5}}
position[i][j] = //I'm confuse here
}
}
I am not certain how to populate pos_x to position[i] and pos_y to position[j].
Thank you
So my guess is this
std::vector<std::vector<float>> position(num, std::vector<float>(2));
for (int i = 0; i < num ; i++){
position[i][0] = pos_x[i];
position[i][1] = pos_y[i];
}
But I could easily be wrong.
UPDATE based on the example in the question I now think this is the correct code
std::vector<std::vector<float>> position(2, std::vector<float>(num));
for (int i = 0; i < num ; i++){
position[0][i] = pos_x[i];
position[1][i] = pos_y[i];
}
There's no such thing as a 2D vector. The truth is that you can create a vector that contains vectors. The first vector is used as an index in the collected vectors.
Note that this concept is similar to a 2D array: arr[3][4] means 3 indices, each one points to 4 data.
To create such 2D vector:
std::vector< std::vector <float>> positions.
Notice I didn't use the second parameter (as in std::vector<float, SomeAllocator> because we don't need this custom memory allocator.
Also notice that, contrary to arrays, I did't tell anything about the sizes of each vector, because the std::vector will take care of it.
Let's populate it.
The "main" vector contains vectors. So these secondary vectors may be created before stored in the "main" one.
std::vector<float> v1; //secondary
positions.push_back(v1); //add it to main vector
Put some values in the secondary:
v1.push_back(7.5);
v1.push_back(-3.1);
Another way is to access through the main vector. If we new this main vector contains v1 in its first index:
positions[0].push_back(8.); // same as v1.push_back(8.) if positions[0] refers to v1
or better using "at": positions.at(0).push_back(8.);
Change some value:
v1.at(1) = 66.88;
or
positions[0].at(1) = 66.88;
You can also do v1[1] = 66.88 but prefer the at() methof because it will check that index "1" is allowed by the size of the vector v1.
You can create and add another secondary vector:
std::vector<float> v2; //secondary
positions.push_back(v2); //add it to main vector
and work with it the same as with previous v1. Now, positions[1] refers to v2
I leave the rest of pulling from other vectors to you.

How to initialize an empty global vector in C++

I have a general question. Hopefully, one of you has a good approach to solve my problem. How can I initialize an empty vector?
As far as I read, one has to know the size of an array at compiling time, though for vectors it is different. Vectors are stored in the heap (e.g. here: std::vector versus std::array in C++)
In my program I want to let the client decide how accurate interpolation is going to be done. That's why I want to use vectors.
The problem is: For reasons of clear arrangement I want to write two methods:
one method for calculating the coefficients of an vector and
one method which is providing the coefficients to other functions.
Thus, I want to declare my vector as global and empty like
vector<vector<double>> vector1;
vector<vector<double>> vector2;
However, in the method where I determine the coefficients I cannot use
//vector containing coefficients for interpolation
/*vector<vector<double>>*/ vector1 (4, vector<double>(nn - 1));
for (int ii = 0; ii < nn - 1; ii++) {vector1[ii][0] = ...;
}
"nn" will be given by the client when running the program. So my question is how can I initialize an empty vector? Any ideas are appreciated!
Note please, if I call another function which by its definition gives back a vector as a return value I can write
vector2= OneClass.OneMethod(SomeInputVector);
where OneClass is an object of a class and OneMethod is a method in the class OneClass.
Note also, when I remove the comment /**/ in front of the vector, it is not global any more and throws me an error when trying to get access to the coefficients.
Use resize:
vector1.resize(4, vector<double>(nn - 1));
Use resize() function as follows:
vector<vector<double>> v;
int f(int nn){
v.resize(4);
for(int i = 0; i < 4; i++){
v[i].resize(nn - 1);
}
}
It look to me that you're actually asking how to add items to your global vector. If so this might help:
//vector containing coefficients for interpolation
for (int i = 0; i < 4; ++i)
vector1.push_back(vector<double>(nn - 1));
for (int ii = 0; ii < nn - 1; ii++)
{
vector1[ii][0] = ...;
}
Unsure if it is what you want, but assign could be interesting :
vector<vector<double>> vector1; // initialises an empty vector
// later in the code :
vector<double> v(nn -1, 0.); // creates a local vector of size 100 initialized with 0.
vector1.assign(4, v); // vector1 is now a vector of 4 vectors of 100 double (currently all 0.)

How can I check if a vector is pointing to null vector in a 2d-vector in c++?

So, I have the following case:
I declared a vector of vector of integers as vector < vector<int> > edges. Basically, I am trying to implement a graph using the above where graph is defined as follows:
class graph
{
public:
int vertices;
vector < vector<int> > edges;
};
Now, during the insertion of an edge, I take input as the starting vertex and ending vertex. Now, I want to do something like this:
void insert(int a, int b, graph *mygraph) // a is starting vertex and b is ending vertex
{
auto it = mygraph->edges.begin();
//int v = 1;
vector<int> foo;
foo.push_back(b);
if (mygraph->edges[a].size() != 0) // Question here?
mygraph->edges[a].push_back(b);
else
mygraph->edges.push_back(foo);
return;
}
Now, in the line marked with Question here, basically, I want to check if the vector for that particular entry exists or not? size is actually wrong because I am trying to call size operation on a vector which doesn't exists. In other words, I want to check, if there is a vector which exists at a particular location in vector of vectors. How can I do it? Something like, mygraph->edges[a] != NULL?
Simply check that a does not exceed size of the vector. If it does, then resize the outer vector.
void insert(int a, int b, graph &mygraph) { // a is starting vertex and b is ending vertex
if (a >= mygraph.edges.size())
mygraph.edges.resize(a+1);
mygraph.edges[a].push_back(b);
}
You can approach your problem in two different ways:
Initialize edges to the number of vertices, and don't allow other vertices to be inserted after that. Why is that?
std::vector< std::vector<int> > v = { {1}, {2} };
// now you need to add an edge between vertex 4 and vertex 5
std::vector<int> edges3;
v.push_back(edges3); // v = { {1}, {2}, {} }
std::vector<int> edges4 = {5};
v.push_back(edges4); // v = { {1}, {2}, {}, {5} }
If you don't want to do it like that, you'd have to do something like this first:
std::vector< std::vector<int> > v;
for (int i = 0; i < maxVertices; i++)
{
std::vector<int> w;
v.push_back(w);
}
// now you need to add an edge between vertex 4 and vertex 5
v[4].push_back(5);
Change the structure used for edges, probably to something better suited for sparse matrices (which looks like your case here, since probably not every vertex is connected to every other vertex). Try:
std::map< int, std::vector<int> > edges;
That way you can match a single vertex with a list of other vertices without the need to initialize edges to the maximum possible number of vertices.
std::vector<int> vertices = {5};
edges[4] = vertices;
Edges is a vector of vectors. Vectors are stored contiguously in memory. You insert elements into a vector from the end. If the size of vector is 10, all 10 members are contiguous and their indexes are going to range from 0-9. If you delete a middle vector, say 5th, all vectors from index 6-9 get shifted up by 1.
The point of saying all this is that you can't have a situation where edges would have an index that doesn't hold a vector. To answer your question, a vector for index a would exist if
a < mygraph->edges.size ();

Using std::max_element on a two dimensional matrix

I have a two dimensional matrix
double TotalEnergy[200][47];
This matrix is populated with appropriate values. Now I am trying to find maximum value in each column.
How do I use std::max_element in this case?
Many thanks.
Best Regards
Chintan
Convert each individual column into a std::vector and use the std::max_element function on the vector. STL containers take care of all memory issues very efficiently without us having to worry about it.
double maxElements[47]; //This will contain the max of each column of TotalEnergy
std::vector<double> vec;
for(int k=0; k<47; k++)
{
for(int l=0; l<200;l++)
vec.push_back(TotalEnergy[l][k]);
maxElements[k] = *std::max_element(vec.begin() , vec.end());
vec.clear();
}
According to cppreference std::max_elements only works with iterators. Unless you want to create an iterator that walks every element of a 2D matrix, I suggest running std::max_element for every row (or column) of the matrix.
Example (untested) code:
double result{std::numeric_limits<double>::min()};
for(int iX{0}; iX < 200; ++iX) {
result = std::max(result, std::max_element(std::begin(TotalEnergy[iX]),
std::end(TotalEnergy[iX])));
}
You can make sure you are using pointers to first and last+1 elements:
double distBetweenNodes[N][N];
const double maxDist = *std::max_element(&distBetweenNodes[0][0], &distBetweenNodes[0][0]+N*N);
// Note that &distBetweenNodes[0][0]+P*N could be &distBetweenNodes[N][N]
I just found that we can do this:
const int n = 555; // for example
int arr[n][n];
// filling the array
int mx = *max_element(begin(arr[0]), end(arr[n-1]));