So, I have the following code in c++:
This is the 2d vector:
vector<vector<int>> adj;
Initialization of 2d vector:
adj[0].push_back(1);
adj[0].push_back(2);
adj[1].push_back(3);
adj[1].push_back(4);
adj[1].push_back(5);
Printing the vector:
for(auto i : adj) {
for(auto j : i)
cout << j << " ";
cout << endl;
}
Compilation is without error but when I try to run it shows nothing.
How to fix this?
When you write adj[0], you're implicitly assuming that the vector has a size of at least 1, in order for the zeroth element to exist. This is not the case for an empty vector, such as a newly initialized one. Unfortunately, this does not guarantee an error of any kind, it is Undefined Behavior, and the compiler is allowed to let literally anything happen. To avoid it, you need to make room for those elements, which can be done in a number of ways:
adj.resize(2); // now size == 2, and [0] and [1] can be safely accessed
adj[0].push_back(1);
adj[1].push_back(3);
or alternatively
adj.push_back({}); // append default-constructed vector
adj.back().push_back(1); // append 1 to the above vector
or, perhaps most concisely:
adj = {
{1, 2},
{3, 4, 5}
};
// adj now contains two vectors containing {1, 2} and {3, 4, 5} respectively
If you want to use the subscript [] operator for indexed access to a vector, consider using vector.at(), which performs the same functionality but throws an exception if the index is out of range. This can be very helpful for debugging.
You can initialize the size of the vector by calling its constructor:
vector< vector<int> > adj(row_size, vector<int>(col_size));
^^^ ^^^^^^^ ^^^
Dimension 1 Element Ctor Dimension 2
Then you can index it like an array.
std::vector operator[] expects an element to exist. It will result in undefined behavior if an undefined element is accessed. Push a std::vector to the outer vector before pushing int to the inner vector. The at() member can be used to safely access any array index with error handling.
#include <vector>
#include <iostream>
int main()
{
std::vector<std::vector<int>> adj(2); // add two std::vector<int>
adj[0].push_back(1);
adj[0].push_back(2);
adj[1].push_back(3);
adj[1].push_back(4);
adj[1].push_back(5);
for(auto const & i : adj) {
for(auto const & j : i)
std::cout << j << " ";
std::cout << std::endl;
}
}
Related
While taking a look at a solution for a problem, I came across this implementation of a vector.
const int MX = 100000;
std::vector <int> adj[MX];
The push_back() function doesn't work with this implementation of the vector class, and to add an element, the following code was used:
std::ifstream fin ("file.in");
int N = 5;
for (int i = 0; i < (N-1); i++) {
int A,B; fin >> A >> B; // reading values from another file
adj[A].pb(B), adj[B].pb(A);
}
The way this code is adding is adding pushing back a value to a certain part of the list, which I imagine as a vector inside the vector of the form:
{
{ },
{ }
}
In addition, how would I loop through this vector because for (int n : adj) does not work. I am not sure what the form of this vector is because this method of looping does not work.
What you have is C style array of vectors, off the bat you could replace that with std::array:
std::array<std::vector<int>, MX> adj;
To loop through these you would have to use a nested one, the outer loop to go through the array, and the inner one to go through each vector, something like this:
const int MX = 3;
//array of 3 vectors
std::array<std::vector<int>, MX> adj {{{1,2,3,4}, {5,6,7,8}, {9, 10, 11, 12}}};
for(auto &v : adj){ //for the array
for(auto i : v){ //for each vector
std::cout << i << " ";
}
std::cout << "\n";
}
Output:
1 2 3 4
5 6 7 8
9 10 11 12
You can also access individual elements using C style indexing:
std::cout << adj[1][0]; // vector element index 0 of array index 1
Or in a safer way, using container member at:
std::cout << adj.at(1).at(0);
This would output 5.
You should be careful though, when randomly filling the array, an array is not meant to have empty elements, otherwise the loops will go through uninitialized array members, which is not ideal, perhaps you are looking for some other kind of container.
Here's the following:
int ia [3][4] = {
{0, 1, 2, 3},
{4, 5, 6, 7},
{8, 9, 10, 11}
};
Normal assignment:
auto p = ia;
This is understandable.
Array ia returns pointer to its first element which is the 1st row of 4 elements (batches of 4 elements).
p has int (*)[4]. Doing a p + 1 will point to the next batch of 4 elements.
Using range for:
for (auto row : ia) {
for (auto col: row)
cout << col << " ";
cout << endl;
}
Why row is not int (*)[4] since each loop it's returning batches of 4 elements just like the previous example?
Instead it is int *.
When I hovered mouse over row variable it gives me int *..
Thanks
The range-based for loop takes each array element and uses it in a declaration or expression derived from your given initializer in each loop round. An array element has type int[4], so for an invented variable int __elem[4] representing the current range element, your loop body effectively says:
const auto row = __elem; // __elem is int[4]
Now this should look familiar: the array expression on the right decays to a pointer to its first element, which has thus type int.
If you want to avoid the decay, you need to bind a reference instead:
const auto& row = __elem; // row is int(&)[4]
Putting this back into your range-based loop, you want:
for (const auto& row : ia) {
for (const int& cell : row) {
// ...
}
}
I have a one-dimensional array of size 10. I want to remove the elements from 5 to 8. Can somebody give me an example of how to do it? This is how I defined my array but I have no idea about how to start.
#include <iostream>
#include <iomanip>
using namespace std;
int array[10] = {1,2,3,4,5,6,7,8,9,10};
So, the output should be 1,2,3,4,5,10. (index 0 = element 1)
Thanks
An alternative to arrays is to use a vector. In this case you can do:
#include <vector>
// create vector for integers
std::vector<int> v;
// set values from 1 to 10
for (int i=1; i<=10; i++)
v.push_back(i);
// erase from 5 to 8
v.erase (v.begin()+5, v.begin()+9);
BTW, if your compiler supports C++11, you can initialize your vector as:
std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
In the above case, its an array of 10 elements array[10]. As the array size is fixed, it may not be possible to remove an item from the array.
Rather, you can assign null or someother value to the corresponding element.
BTW, I would rather use, std::list or std:: vector instead of array.
Anyhow, If you mean to get rid of that element, you'd need to shift all the ones to the right of that element one to the left:
for (int i = index; i < /* length */; i++)
array[index] = array[index+1];
array[length-1] = 0;
You can't literally remove them because C++'s built-in arrays (like C's) are fixed-size.
What you can do is overwrite them with the values that come after them, and then (if you want to) zero out the four now-extra positions at the end of the array. e.g.:
// copy latter values over the values we don't want
for (int i=4; i<6; i++) array[i] = array[i+4];
// zero out the no-longer-necessary values at the end, just so they won't appear valid anymore
for (int i=6; i<10; i++) array[i] = 0;
and then when printing the array, print only the first 6 values rather than all 10, since your array is (conceptually, even if not actually) "shorter" now.
Not sure what exactly you want your output to be, so I'm just providing another possible solution here:
// your input
int array[10] = {1,2,3,4,5,6,7,8,9,10};
// 1. put all invalid element in the back of the array
// "it" points to the first invalid element
int* it = std::remove_if(std::begin(array), std::end(array),
[](int e)
{
return (e >= 5) && (e <= 8);
});
// 2. then, mark them as -1 (from "it" to the last element)
std::transform(it, std::end(array), it,
[](int e) -> int
{
return -1;
});
// now the array contains:
// {1,2,3,4,9,10,-1,-1,-1,-1}
#include <iostream>
#include <vector>
int main()
{
static const unsigned TOTAL = 4;
std::vector<int> v[TOTAL];
v[2].push_back(37);
//std::cout << v.size(); error
std::cout << v[0].size();
std::cout << v[2].size();
return 0;
}
Is is valid to instatnitate std::vector with bracket like in the code above?
MSVS and ideone compile it just fine, but vector is messed up (see error line).
I know I can use resize, but what is going on here?
You are creating a TOTAL sized array of vectors.
What you need is
std::vector<int> v(TOTAL);
This constructs a vector with TOTAL zero-initialized ints.
Then,
std::cout << v.size() << std::endl; // prints 4
std::cout << v[0] << std::endl; // prints 0
and so on.
It is valid to instantiate std::vector with bracket like in the code, but with different meanings.
std::vector<int> v[TOTAL];
Here you defined a vector v of size=TOTAL, each element of which is a vector<int>. Initially, these TOTAL vector<int>s are all empty (i.e. size=0).
After you call v[2].push_back(37);, v[2] will become a vector<int> of size=1 with a value 37 in it.
So the output you for the following will be 0 and 1.
std::cout << v[0].size();
std::cout << v[2].size();
If you want to call size(), you should call v[i].size() or define it as vector<int> v(TOTAL); (v is a vector of size=TOTAL, each element of which is an int).
I know I can use resize, but what is going on here?
you are basicly creating an array of type std::vector<int>, just as in here:
int arr[TOTAL];
Is is valid to instatnitate std::vector with bracket like in the code above?
you can have an array of vectors, but from your post it is not what you are after.
If you want to give your vector some initial size then use
std::vector<int> v(TOTAL);
this will set initial size of your vector to TOTAL, and value initialize all elements (set them to zero).
But you might actually want to:
std::vector<int> v;
v.reserve(TOTAL); // this is not necessary
// v.size() is zero here, push_back will add elements starting from index 0
because in case of std::vector<int> v(TOTAL); your push_back will start adding from index TOTAL.
This question already has answers here:
Appending a vector to a vector [duplicate]
(4 answers)
Closed 9 years ago.
My apologies for the title, I did not know of a better one.
So, basically, I have a 1D vector, which I extract 256 pieces of data from this, until there is no more data left.
std::size_t begin = 0;
std::size_t nextEnd = 0;
while (nextEnd < signal.size()) {
begin = nextEnd;
nextEnd += 256;
Transform(signal, begin, std::min(nextEnd, signal.size()));
}
Inside the "Transform" function, there is a new, temp vector created called temp_vector and inside my main I have a global 1D vector.
What I want to do is, every iteration of this loop, the values of the temp_vector is pushed back into the global 1D vector at the right position.
So for example:
std::vector<double> global;
std::vector<double> actual = {1,1,0,0,2, 3, 4 ....., n};
// here loop over n number of elements
// TRANSFORM:
// std::vector<double> temp_vector = {10, 50}; // after calculations
// global.push_back(temp_vector);
So at the end result, the global_vector will still be a 1D vector, however, will contain all of the values, in the same place for each of the elements.
I hope I have explained myself enough!
Here is code for array merging:
#include <vector>
#include <iostream>
int main() {
std::vector<int> glob = {1, 2, 3};
std::vector<int> temp_vector = {4, 5, 6};
glob.insert(glob.end(), temp_vector.begin(), temp_vector.end());
std::vector<int>::const_iterator it = glob.begin();
for(; it != glob.end(); ++it) {
std::cout << *it << ", ";
}
return 0;
}
Output:
./a.out
1, 2, 3, 4, 5, 6,
Consider to use an ordered container like std::set or std::priority_queue and insert into that container directly, not using a temporary.