Why can't we input a vector as we input an array in C++? - c++

The wiki says:
The elements of a vector are stored contiguously. AND
Vectors allow random access; that is, an element of a vector may be referenced in the same manner as elements of arrays (by array indices).
So why can't we input the elements of a vector as:
vector<int> v;
for(int i=0;i<3;i++)
{
cin>>v[i];
}

Either you need to resize the vector upfront - as other answers say - or you can use C++ standard library. Then the equivalent of your for loop is the following one line:
copy_n(istream_iterator<int>(cin), 3, back_inserter(v));
and it takes care of allocation/resizing.

Your vector has zero elements right now. Try allocating it some space as:
vector<int> v(5);
Then your method would work.

The problem is that you need to allocate the elements of the vector first. So try vector<int> v(4);, so it will start with 4 elements. Then you can load values into them.

Related

What does this mean in vectors in c++?

vector<int> v[1000];
Is this for reserving space for the vector? But isn't the command for reserving space ()? What does this do?
That is an array, with each element being a vector, so there are 1000 default-constructed (empty) vectors.
However, if you wanted to make a single vector of 1000 int, you would say
vector<int> v(1000);

Difference between vector <int> V[] and vector< vector<int> > V

vector <int> V[] and vector< vector<int> > V both are 2D arrays.
But what is the difference between them and where do we use each one? Please give a brief explanation.
vector<int> V[] is an array of vectors.
vector< vector<int> > V is a vector of vectors.
Using arrays are C-style coding, using vectors are C++-style coding.
Quoting cplusplus.com ,
Vectors are sequence containers representing arrays that can change in
size.
Just like arrays, vectors use contiguous storage locations for their
elements, which means that their elements can also be accessed using
offsets on regular pointers to its elements, and just as efficiently
as in arrays. But unlike arrays, their size can change dynamically,
with their storage being handled automatically by the container.
TL;DR:
When you want to work with a fixed number of std::vector elements, you can use vector <int> V[].
When you want to work with a dynamic array of std::vector, you can use vector< vector<int> > V.
One difference would be that although both can be initialized in the same way, e.g.
vector<int> V1[] {{1,2,3}, {4,5,6}};
vector<vector<int>> V2 {{1,2,3}, {4,5,6}};
and accessed
cout << V1[0].back() << endl;
cout << V2[0].back() << endl;
the V1 can't grow. You cannot make V1.push_back(...) as its not a vector object. Its just an array. Second one is dynamic. You can grow it as you please.
vector<vector<int>> v(26); is a vector containing vectors. In this example, you have a vector with 26 vectors contained in it. The code v[1].push_back(x) means that x is pushed back to the first vector within the vectors.
vector<int> a[26]; is an array of vectors. In other words, a one-dimensional array containing 26 vectors of integers. The code a[1].push_back(x); has x being pushed back to the first index of the array.
vector<int> v[] is an array of vectors. That is, it is an array which contains vectors as its elements.
So, you cannot change the size of the array part, but we can add to its elements which is vector.
For example,
1.vector<int> v1[] = {{1},{2},{3}}; // array that contains 3 vector elements.
2.vector<vector<int>> v2 = {{1},{2},{3}}; // vector that contains 3 vector elements.
So for the first we cannot change the size of v but we can add or delete elements to its elements since it is a vector.
v1.push_back(4); // this will give an error since we cannot the predefined size of array.
v1[1].push_back(4); // this is acceptable since we are changing the vector part.
This makes the v1 {{1},{2,4},{3}}
For the second one, we can change both the overall size and its elements.
v2.push_back(4); // this is acceptable since it is vector.
vector V[] is just a fixed array; and so you can add/modify only till the upper limit. It is not a vector per se, and so has a fixed size limit.
However vector< vector > V is a dynamic vector and its size can be increased dynamically.

Inserting elements into 2D vector

so I'm creating a class that implements an adjacency list. Currently in my class definition I initialized two vectors:
vector<vector<int>> adjList;
vector<int> neighbors;
and I declared two functions that I plan to use to make it:
bool constructAdjList();
bool insertIntoAdjList(int, int);
It's getting difficult wrapping my head around 2D vectors. I understand that it is essentially a vector of vectors, but I'm confused about how to insert a new value into one of the "subvectors". For example, I am able to create an adjacency list in createAdjList that is empty with the following loop:
for (int i = 0; i < numOfValues; i++){
neighbors.push_back(0);
adjList.push_back(neighbors);
neighbors.clear();
}
But how can I say, push_back the value 5 to the 4th vector in adjList, which would be represented in my insertIntoAdjList function as
insertIntoAdjList(4, 5);
I know I can access a specific value in a 2D vector by saying adjList[4][1], but how can I push one onto it?
Thanks!
To push on the vector that is an element of another vector, you simply do this
adjList[x].push_back();
If initially you do not have any values in the vector -
You can push values into one vector and then push this vector into the 2D vector.
For example:
vector< vector<int> > vt1;
vector<int> vt2;
vt2.push_back(value);
vt1.push_back(vt2);
If your vector is already populated then -
vt1[index].push_back(value);
A couple of notes here.
Your loop can be significantly shortened just be using the constructors of your two members:
vector<int> neighbors(1, 0); // set to length 1, value is zero
vector<vector<int>> adjList(numOfValues,neighbors); // "outer" vector is numOfValues long
. // each row is a *COPY* of neighbor
If you can't do this at construction time (maybe numOfValues isn't known yet), then there's still a better loop phrasing we can use:
// neighbors object can be reused
neighbors.clear(0);
neighbors.push_back(0);
adjList.reserve(numOfValues); // reserving memory ahead of time will prevent allocations
for (int i = 0; i < numOfValues; i++){
adjList.push_back(neighbors); // push_back is by *COPY*
}
In your example, by using clear and push_back to essentially build the same vector every loop iteration, you are risking an allocation and deallocation each iteration. In practice, most implementations won't do this, but if we can both shorten and potentially make things more efficient, we may as well.
Lastly, if the number of neighbors is relatively small and similar row to row (for instance a finite elements code with tetrahedral elements, where each element connects to ~5 others), then as others have suggested you may be better off with a different structure than vector-of-vector. For instance, a single vector that is logically organized such that a new "row" begins every N elements.

Initializing and setting a vector<int>

vector<int> v;
v.push_back(0); //you have to do this
//v[0] = 0; //this gives you an error
v[0] = 1000000; //but now you can set it
So, how come the first time you initialize a vector, you have to push_back, and after that you can just set it? For a primitive type, say int, you can do int i = 0; for initialization.
If you know in advance the size of your vector, definitively don't use a plain sequence of push_back()'s, since it may be a waste of time reallocating if your vector is large (say, >512 elements).
Better do:
OPTION 1: Preallocating and pushing
vector<int> v;
v.reserve(N); // N is the expected size, but right now [0] is undefined.
for (...) {
v.push_back(...); // No problems in adding more than N elements, but may have to reallocate.
}
OPTION 2: Resizing and filling
vector<int> v;
v.resize(N);
for (size_t i=0;i<N;i++)
v[i] = ...; // You can't write past N-1 here!
OPTION 3: Create directly with the correct size, then fill
vector<int> v(N);
for (size_t i=0;i<N;i++)
v[i] = ...; // You can't write past N-1 here!
OPTION 4: Create a vector with the correct size and initialized to some fixed value
vector<int> v(N,val); // v[0:N-1] are all equal to val
Because when you first create a vector it is empty so vector[0] doesn't exist. push_back adds an element to the vector then you can modify or read it with vector[i]
Just to make everything 100% clear, your declaration of a vector,
vector<int> v;
is in some sense similar to the declaration of a variable:
int x;
and if you then want, say,
cout << x;
you will get rubbish. Though, if you declare
int x(2);
everything will be fine. Similarly for vectors: declaration of
vector<int> v;
allocates some memory space for a vector, but not fills it. You can then specify
vector<int> v(2);
which means that you now have declared a vector of two elements, or go for a vector-only feature - push_back. This would add elements to your vector, as you've noticed.
Because std::vector<int> isn't std::map<int, int>.
std::vector requires you to manually push_back() or (in C++11) emplace_back() elements for them to be included in the collection. And of course some of its constructors allows you to include initial elements to it. And of course again its assignment operators.
The subscript([]) operator should only be used in reading and/or modifying existing elements. Indexing using operator[] out-of-bounds (non-existent) elements would result in undefined behavior.
You can't access v[0] because there is no v[0] yet. The vector starts off default-constructed as an empty vector. You push an element onto the back and it grows in size by 1. You're then able to access the element you just added. If you want it to start off with one element, use the appropriate constructor:
std::vector<int> v(1); //one zeroed integer
You're comparing apples and oranges. int i = 0; would be like std::vector<int> v;.
You should first allocate memory for setting element values, such as
v.resize(new_size);
or use push_back method to add elements.

dynamically changing name of an array in c++

Hi I have a problem where at compile time, I don't know how many vectors in my program are needed. The number required depends on a data set given at run-time, which will results in the range of vectors needed to be from 1 to N.
So if the data set requires ten vectors, it will create vec1,vec2,......vecN
How can i dynamically create the vectors so that they all have a different name?
I would then need to call each array separately. Presumably
I could just use strings and a few loops for this.
You can't do that directly. However, you could use a map to store a vector name, and the vector itself:
map<string, vector<int> > myMap;
You can add elements simply like this (if the element with such key doesn't exist yet):
vector<int> vec;
myMap["vec"] = vec;
If you'll do it with a key that already exists, the value will be replaced. For example:
vector<int> vec;
vector<int> vec1;
myMap["vec"] = vec;
myMap["vec"] = vec1;//now myMap["vec"] holds the vec1 vector
You can also easlly access elements like this:
myMap["vec"]//this will access the vector with the key "vec1"
You can create a vector to contain your vectors:
std::vector<std::vector<int>> my_vector_of_vectors;
// Add a vector
my_vector_of_vectors.push_back(std::vector<int>{});
// Add a number to the inner vector
my_vector_of_vectors[0].push_back(1);
you have a vector of vectors, vec[0] to vec[n], each one containing the vector.
However, this works est if you know the number of vectors (eg 10). If you need to add new ones on-demand, then a list of vectors or a map might be a better option for you.