Looping through a vector of lists - c++

So I was learning about the stlibrary and graphs, and so I found out that graphs could be represented as a vector of lists which could be like this, where the 1 2 3 4 5 6 are the vertices, and from the vertice 1 I could go to the number 2, from the 3 to the 6, etc.
1 2 3 4 5 6
2 6 1 2
2
But, I already saved these values in the vector list, how could I loop through it to get the graph? My vector list is called _verticesEdges.
Like, to get an output like this:
Vertice 1: 2
Vertice 2:
Vertice 3: 6
Vertice 4: 1 2
Vertice 5:
Vertice 6: 2
Appreciate your help!

Assuming you have stored from index 1 to n (that means size of 0th index of your vector is zero), where n is number of vertices,
for (int i = 1; i <= n; i++)
{
cout << "Vertex " << i << ": ";
for (int j=0; j< _verticesEdges[i].size(); j++)
cout << _verticesEdges[i][j] << " ";
cout << "\n";
}

Something like this
std::vector<std::list<int>> vecOfLists;
// fill vecOfLists;
for (size_t i = 0; i < vecOfLists.size(); ++i) {
std::cout << "Vertice " << i + 1 << ": ";
for (int num : vecOfLists[i]) {
std::cout << num << " ";
}
std::cout << std::endl;
}
I am using usual for for iterating through lists, since index is required, and using range-based for for iterating through list, since this is better and modern way to iterate through whole container if you don't require indexes.

Related

Values in vector showing 0 when printed

I have been practicing with vectors, when I try to print the values with the length set, output is 0, but when I try to print the values without the length set, it shows correct values.
A question like this has been answered before but I didnt really get it.
Here's the code:-
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int size,val;
cout << "Enter vector length " << endl;
cin >> size;
vector<int> vec(size);
for(int i = 0; i < size; i++){
cout << "Enter number for index " << i+1 << endl;
cin >> val;
vec.push_back(val);
}
for(int i = 0; i < size; i++){
cout << "Numeber at index " << i+1 << " is " << vec[i] << endl;
}
}
Output:-
Enter vector length
3
Enter number for index 1
1
Enter number for index 2
2
Enter number for index 3
3
Numeber at index 1 is 0
Numeber at index 2 is 0
Numeber at index 3 is 0
With value not set:-
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int size,val;
cout << "Enter vector length " << endl;
cin >> size;
vector<int> vec;
for(int i = 0; i < size; i++){
cout << "Enter number for index " << i+1 << endl;
cin >> val;
vec.push_back(val);
}
for(int i = 0; i < size; i++){
cout << "Numeber at index " << i+1 << " is " << vec[i] << endl;
}
}
Output:-
Enter vector length
3
Enter number for index 1
1
Enter number for index 2
2
Enter number for index 3
3
Numeber at index 1 is 1
Numeber at index 2 is 2
Numeber at index 3 is 3
Help!!!
When you call push_back on a vector you are adding items to the end of it.
In the second example you push_back to it 3 times to the length of the vector is 3.
[] <-- vector is constructed
[ 1 ] <-- push_back(1)
[ 1, 2 ] <-- push_back(2)
[ 1, 2, 3 ] <-- push_back(3)
In the first example, when you set the length to be 3, those values are initialized to zero. Then you push_back 3 times so the final length of the vector is 6 and the first 3 values are still 0.
[ 0, 0, 0 ] <-- vector is constructed
[ 0, 0, 0, 1 ] <-- push_back(1)
[ 0, 0, 0, 1, 2 ] <-- push_back(2)
[ 0, 0, 0, 1, 2, 3 ] <-- push_back(3)
If you want to increase the CAPACITY of the vector but not the SIZE you want vector.reserve
There are two ways to do what you are trying to do.
One is the way you did it in your second trial.
The other is to modify your first trial's code:
Instead of vec.push_back(val);, try accessing the index directly:
vec.at(i) = val;
Both methods work fine.
The issue with your first trial was you resized a vector then appended values instead of doing what you thought it would do.
Basically, the vector was resized to size so all the elements from index 0 to size-1 were all set to 0, which is the default int value for vectors. After that, you appended new integers to the back of the vector. The reason your second trial worked is because the size of the vector started at 0, then you appended new integers to the back with your calls to push_back(int) in your for loop.
An important note: I would rephrase your output. Instead of saying "Number at index" << i + 1, change it to Number at element. The index numbering starts at 0. Element numbering starts at 1. As in: element 1 is located at index 0.

How to std::vector resize assigning default value

I have std::vector<bool> v
I want to resize it and put false value to all its elements. How can I do it efficiently (without loop)
How can I do it?
If v has already been constructed, you can use assign method to achieve your goal.
v.assign(count, false);
NOTE: vector<bool> might be space-efficient optimized, and behaves different than other types of vector, e.g. the underlying storage might not be contiguous. And you might want to replace it with vector<int> or bitset<N>. You can check the doc for detail.
You can use the following approach
#include <iostream>
#include <vector>
using namespace std;
int main(void) {
vector<bool> v(5,true);
cout << "Initial size = " << v.size() << endl;
/* displaying Initial vector values */
for (int i = 0; i < v.size(); ++i)
cout << v[i] << " ";
cout<<endl;
/*
Resize it to required length
Parameters:
1st argument – it is a new container size, expressed in a number of elements.
2nd argument – if this parameter is specified then new elements are
initialized with this value.
*/
v.resize(10,false);
cout << "Size after resize = " << v.size() << endl;
/* displaying current vector values */
for (int i = 0; i < v.size(); ++i)
cout << v[i] << " ";
cout<<endl;
/*
assign new values to the vector
1. length upto which new values are to be assigned
2. value to be assign
*/
v.assign(v.size(),false);
cout << "size after assign = " << v.size() << endl;
/* display modified vector values */
for (int i = 0; i < v.size(); ++i)
cout << v[i] << " ";
return 0;
}
Ouput:
Initial size = 5
1 1 1 1 1
Size after resize = 10
1 1 1 1 1 0 0 0 0 0
size after assign = 10
0 0 0 0 0 0 0 0 0 0

vectors in range based for loop

I was testing vector to vector initialization, I used range based for loop it gives different output.
with respect to Normal for loop.
vector<int> intVector;
for(int i = 0; i < 10; i++) {
intVector.push_back(i + 1);
cout << intVector[i] << endl;
}
cout << "anotherVector" << endl;
vector<int> anotherVector(intVector);
for(auto i : anotherVector)
cout << anotherVector[i] << endl;
//for(unsigned int i = 0; i < anotherVector.size(); i++) {
// cout << anotherVector[i] << endl;
//}
this range based for loop gives the output - Linux ubuntu
Output
STLTest Cunstructor Called.
1
2
3
4
5
6
7
8
9
10
anotherVector
2
3
4
5
6
7
8
9
10
81
2.
vector<int> intVector;
for(int i = 0; i < 10; i++) {
intVector.push_back(i + 1);
cout << intVector[i] << endl;
}
cout << "anotherVector" << endl;
vector<int> anotherVector(intVector);
//for(auto i : anotherVector)
// cout << anotherVector[i] << endl;
for(unsigned int i = 0; i < anotherVector.size(); i++) {
cout << anotherVector[i] << endl;
}
This gives different output.
output
STLTest Cunstructor Called.
1
2
3
4
5
6
7
8
9
10
anotherVector
1
2
3
4
5
6
7
8
9
10
why both for loop acting differently?
for(auto i : anotherVector)
cout << anotherVector[i] << endl;
This code doesn't do what you think it does. The range-based for loop iterates over values, not over indices. In other words, the loop variable (i) is assigned all ements of the vector in turn.
To replicate the functionality of your first loop, you need this:
for (auto i : anotherVector)
cout << i << endl;
What your original code was doing was take an element of the vector, and use it to index into the vector again. That's why the numbers were off by one (since the vector held number n + 1 at position n). Then, the final output (81 in your case) was effectively random and the result of Undefined Behaviour—you were reaching past the end of the vector.

Generating N choose K Permutations in C++ [duplicate]

This question already has answers here:
Implementation of Permutation, Combinations and PowerSet in C++ [duplicate]
(2 answers)
Closed 8 years ago.
I have a function that receives n and k to create all the possible permutations of n choose k, and while it works for most combinations like 5 choose 3 or 3 choose 2, it doesn't for for others like 4 choose 2. I need some help finding and understanding the bug. Thanks for looking.
The function:
void PermGenerator(int n, int k)
{
int d[] = {1,2,3,4,5,6,7,8,9};
sort (d, d+n);
cout << "These are the Possible Permutations: " << endl;
do
{
for (int i = 0; i < k; i++)
{
cout << d[i] << " ";
if (i == k-1) cout << endl;
}
} while (next_permutation(d, d+n));
}
I'm using the next_permutation function. cplusplus
When I try 4 choose 2, I should be getting 12 permutations, instead I get this:
1 2
1 2
1 3
1 3
1 4
1 4
2 1
2 1
2 3
2 3
2 4
2 4
3 1
3 1
3 2
3 2
3 4
3 4
4 1
4 1
4 2
4 2
4 3
4 3
Whereas, 3 choose 2 works perfectly with 6 possible permutations:
1 2
1 3
2 1
2 3
3 1
3 2
The first k values are repeated n-k factorial times. Here is an easy, although inefficient, way to avoid the repetition:
int Factorial(int n)
{
int result = 1;
while (n>1) {
result *= n--;
}
return result;
}
void PermGenerator(int n, int k)
{
std::vector<int> d(n);
std::iota(d.begin(),d.end(),1);
cout << "These are the Possible Permutations: " << endl;
int repeat = Factorial(n-k);
do
{
for (int i = 0; i < k; i++)
{
cout << d[i] << " ";
}
cout << endl;
for (int i=1; i!=repeat; ++i)
{
next_permutation(d.begin(),d.end());
}
} while (next_permutation(d.begin(),d.end()));
}
However, there is an even easier and more efficient way to do it using std::reverse (from https://stackoverflow.com/a/2616837/951890)
void PermGenerator(int n, int k)
{
std::vector<int> d(n);
std::iota(d.begin(),d.end(),1);
cout << "These are the Possible Permutations: " << endl;
do
{
for (int i = 0; i < k; i++)
{
cout << d[i] << " ";
}
cout << endl;
std::reverse(d.begin()+k,d.end());
} while (next_permutation(d.begin(),d.end()));
}
The trick here is to realize that the last permutation is just the reverse of the first permutation, so by reversing the last n-k elements, you automatically skip to the last permutation of those elements.
You may use the following:
template <typename T>
void Combination(const std::vector<T>& v, std::size_t count)
{
assert(count <= v.size());
std::vector<bool> bitset(v.size() - count, 0);
bitset.resize(v.size(), 1);
do {
for (std::size_t i = 0; i != v.size(); ++i) {
if (bitset[i]) {
std::cout << v[i] << " ";
}
}
std::cout << std::endl;
} while (std::next_permutation(bitset.begin(), bitset.end()));
}
Live example
You output first k members of every n! permutations.
4! = 24 permutations. First two permutations are
1,2,3,4
1,2,4,3
and you have got 1,2 and 1,2
To get combinations (4,2), you might, for example, use vector
{0,0,1,1}
permute it, and output indexes of 1's

vector::erase does not erase the desired element, but instead erases the last element from the vector

I've been working on learning c++, but now I'm stuck with a problem that really confuses me. The problem is that when i try to erase an element from a vector, the erase function does not erase the element that i wanted to be erased, but instead erases the last element from the vector. I recreated the problem with this piece of code, so that it's easier to understand my problem than it would be with my whole code:
#include <vector>
#include <iostream>
int main()
{
std::vector<int> c;
for(int i=0; i<=10; i++){
c.push_back(i);
}
for (int i=0;i<c.size();i++) {
std::cout << i << " ";
}
std::cout << '\n';
c.erase(c.begin()+2);
for (int i=0;i<c.size();i++) {
std::cout << i << " ";
}
std::cout << '\n';
c.erase(c.begin()+2, c.begin()+5);
for (int i=0;i<c.size();i++) {
std::cout << i << " ";
}
std::cout << '\n';
}
the result is not what is expected:
0 1 2 3 4 5 6 7 8 9 10
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6
when I thought the result would be
0 1 2 3 4 5 6 7 8 9 10
0 1 3 4 5 6 7 8 9 10
0 1 2 7 8 9 10
Am I doing something completely wrong, or why is this not working as I thought it would?
If it is relevant, I'm using the MinGW compiler for windows.
After deletion, you do not print the content of the vector but only the loop variable.
Simply replace your cout sections by
for (int i=0;i<c.size();i++) {
std::cout << c[i] << " ";
}
and it will work as desired.
You print the loop variable, instead of the contents of the vector. For all instances:
Change
for (int i=0;i<c.size();i++) {
std::cout << i << " ";
}
to
for (int i=0;i<c.size();i++) {
std::cout << c.at(i) << " ";
}
for (int i=0;i<c.size();i++) {
std::cout << i << " ";
}
should be:
for (int i=0;i<c.size();i++) {
std::cout << c[i] << " ";
}
EDIT: I was late.