I was looking at a basic implementation of a graph with an adjacency list, and I noticed to represent the addition of an edge between two nodes, push_back could be used multiple times on a single index. I tried it myself with this:
int V = 3;
vector<int> vec[V];
vec[0].push_back(23);
vec[0].push_back(24);
vec[1].push_back(52);
vec[2].push_back(4);
vec[2].push_back(-1);
I printed them out and it all worked fine:
for(int i=0; i<V; ++i) {
for(auto p : vec[i])
cout << p << ' ';
cout << '\n';
}
How come multiple p can come from the same index i? Am I over/under-thinking something and this behavior should be expected? I thought that a vector was just an array that could change size, not that one of its positions could hold many elements.
Well, you might be misunderstanding the workings of the output code
for(int i=0; i<V; ++i) { // for each vector element in the array vec[3]
for(auto p : vec[i]) // for each element in the vector.
cout << p << ' ';
cout << '\n';
}
Each p is a vector, holding many elements. vec is an array holding 3 elements.
If you have lots of edges this might be an optimization, otherwise you can just do a
struct edge{ int from; int to; double weight; };
std::vector<edge> E;
This will simplify your implementation of algorithms.
I'm trying to learn C++ vectors.. Here is the code:
#include <iostream>
#include <vector>
using namespace std;
int main(){
vector <int> vec;
for(int i=0; i<=10; i++){
vec.push_back(i);
}
for(auto i=vec.begin(); i!=vec.end();i++){
cout<<*i<<" ";
}
}
Can anybody tell me what this part is?
for(auto i=vec.begin(); i!=vec.end();i++){
cout<<*i<<" ";
}
I've searched the Internet but couldn't find a clear explanation.
Ok, it prints the numbers that we put it in the vector, but can I get a more technical explanation?
for(auto i=vec.begin(); i!=vec.end();i++){
cout<<*i<<" ";
}
This is just the iterators in C++.
begin() function is used to return an iterator pointing to the first element of the vector.
Similarly, end() function is used to return an iterator pointing past the last element of the vector.
auto just deduces the type of the variable i. You could have also specified it as std::vector<int>::iterator i = vec.begin() . That's the type of the iterator you are using to loop over the vector.
In the above piece of code, you are basically iterating from the beginning of the vector until the end of the vector.
Inside the loop, you are just dereferencing the iterator and printing the value at the current position where the iterator is.
What the above piece of code is doing is basically the same as the following type of loop, which uses indexing to loop over the array:
for(size_t i = 0; i != vec.size() ; i++){
cout << vec[i] << " ";
}
You should read more about iterators, as they are a core concept in C++. You can read more about them here:
iterators
std::vector.begin()
std::vector.end()
This is an iterator to the first element in the vector: vec.begin()
An iterator to one-past the last element of the vector: vec.end()
auto deduces the type of i from vec.begin(), its an iterator. We really do not need to care about the exact type.
We only need to know that we can increment it: i++.
And compare two iterators with each other to check if we are at the end: i != vec.end().
And we can derference iterators to get the element the "point to": *i.
Without iterators the loop could be written as:
for (size_t i=0; i<vec.size(); ++i) {
std::cout << vec[i];
}
That part simply prints all the elements of the vector. auto automatically determines what data structure it is given the parameters that define it. In this case, it is being used as a vector<int>::iterator. Mostly, this is used in other data structures, such as a map or a set, since those don't support random access. In a vector, you can simply do
for(int i = 0; i < vec.size(); i++)
{
cout << vec[i] << " ";
}
I have a std::vector<int>, and I want to delete the n'th element. How do I do that?
std::vector<int> vec;
vec.push_back(6);
vec.push_back(-17);
vec.push_back(12);
vec.erase(???);
To delete a single element, you could do:
std::vector<int> vec;
vec.push_back(6);
vec.push_back(-17);
vec.push_back(12);
// Deletes the second element (vec[1])
vec.erase(std::next(vec.begin()));
Or, to delete more than one element at once:
// Deletes the second through third elements (vec[1], vec[2])
vec.erase(std::next(vec.begin(), 1), std::next(vec.begin(), 3));
The erase method on std::vector is overloaded, so it's probably clearer to call
vec.erase(vec.begin() + index);
when you only want to erase a single element.
template <typename T>
void remove(std::vector<T>& vec, size_t pos)
{
std::vector<T>::iterator it = vec.begin();
std::advance(it, pos);
vec.erase(it);
}
The erase method will be used in two ways:
Erasing single element:
vector.erase( vector.begin() + 3 ); // Deleting the fourth element
Erasing range of elements:
vector.erase( vector.begin() + 3, vector.begin() + 5 ); // Deleting from fourth element to sixth element
Erase an element with index :
vec.erase(vec.begin() + index);
Erase an element with value:
vec.erase(find(vec.begin(),vec.end(),value));
Actually, the erase function works for two profiles:
Removing a single element
iterator erase (iterator position);
Removing a range of elements
iterator erase (iterator first, iterator last);
Since std::vec.begin() marks the start of container and if we want to delete the ith element in our vector, we can use:
vec.erase(vec.begin() + index);
If you look closely, vec.begin() is just a pointer to the starting position of our vector and adding the value of i to it increments the pointer to i position, so instead we can access the pointer to the ith element by:
&vec[i]
So we can write:
vec.erase(&vec[i]); // To delete the ith element
If you have an unordered vector you can take advantage of the fact that it's unordered and use something I saw from Dan Higgins at CPPCON
template< typename TContainer >
static bool EraseFromUnorderedByIndex( TContainer& inContainer, size_t inIndex )
{
if ( inIndex < inContainer.size() )
{
if ( inIndex != inContainer.size() - 1 )
inContainer[inIndex] = inContainer.back();
inContainer.pop_back();
return true;
}
return false;
}
Since the list order doesn't matter, just take the last element in the list and copy it over the top of the item you want to remove, then pop and delete the last item.
It may seem obvious to some people, but to elaborate on the above answers:
If you are doing removal of std::vector elements using erase in a loop over the whole vector, you should process your vector in reverse order, that is to say using
for (int i = v.size() - 1; i >= 0; i--)
instead of (the classical)
for (int i = 0; i < v.size(); i++)
The reason is that indices are affected by erase so if you remove the 4-th element, then the former 5-th element is now the new 4-th element, and it won't be processed by your loop if you're doing i++.
Below is a simple example illustrating this where I want to remove all the odds element of an int vector;
#include <iostream>
#include <vector>
using namespace std;
void printVector(const vector<int> &v)
{
for (size_t i = 0; i < v.size(); i++)
{
cout << v[i] << " ";
}
cout << endl;
}
int main()
{
vector<int> v1, v2;
for (int i = 0; i < 10; i++)
{
v1.push_back(i);
v2.push_back(i);
}
// print v1
cout << "v1: " << endl;
printVector(v1);
cout << endl;
// print v2
cout << "v2: " << endl;
printVector(v2);
// Erase all odd elements
cout << "--- Erase odd elements ---" << endl;
// loop with decreasing indices
cout << "Process v2 with decreasing indices: " << endl;
for (int i = v2.size() - 1; i >= 0; i--)
{
if (v2[i] % 2 != 0)
{
cout << "# ";
v2.erase(v2.begin() + i);
}
else
{
cout << v2[i] << " ";
}
}
cout << endl;
cout << endl;
// loop with increasing indices
cout << "Process v1 with increasing indices: " << endl;
for (int i = 0; i < v1.size(); i++)
{
if (v1[i] % 2 != 0)
{
cout << "# ";
v1.erase(v1.begin() + i);
}
else
{
cout << v1[i] << " ";
}
}
return 0;
}
Output:
v1:
0 1 2 3 4 5 6 7 8 9
v2:
0 1 2 3 4 5 6 7 8 9
--- Erase odd elements ---
Process v2 with decreasing indices:
# 8 # 6 # 4 # 2 # 0
Process v1 with increasing indices:
0 # # # # #
Note that on the second version with increasing indices, even numbers are not displayed as they are skipped because of i++
Note also that processing the vector in reverse order, you CAN'T use unsigned types for indices (for (uint8_t i = v.size() -1; ... won't work). This because when i equals 0, i-- will overflow and be equal to 255 for uint8_t for example (so the loop won't stop as i will still be >= 0, and probably out of bounds of the vector).
If you work with large vectors (size > 100,000) and want to delete lots of elements, I would recommend to do something like this:
int main(int argc, char** argv) {
vector <int> vec;
vector <int> vec2;
for (int i = 0; i < 20000000; i++){
vec.push_back(i);}
for (int i = 0; i < vec.size(); i++)
{
if(vec.at(i) %3 != 0)
vec2.push_back(i);
}
vec = vec2;
cout << vec.size() << endl;
}
The code takes every number in vec that can't be divided by 3 and copies it to vec2. Afterwards it copies vec2 in vec. It is pretty fast. To process 20,000,000 elements this algorithm only takes 0.8 sec!
I did the same thing with the erase-method, and it takes lots and lots of time:
Erase-Version (10k elements) : 0.04 sec
Erase-Version (100k elements) : 0.6 sec
Erase-Version (1000k elements): 56 sec
Erase-Version (10000k elements): ...still calculating (>30 min)
I suggest to read this since I believe that is what are you looking for.https://en.wikipedia.org/wiki/Erase%E2%80%93remove_idiom
If you use for example
vec.erase(vec.begin() + 1, vec.begin() + 3);
you will erase n -th element of vector but when you erase second element, all other elements of vector will be shifted and vector sized will be -1. This can be problem if you loop through vector since vector size() is decreasing. If you have problem like this provided link suggested to use existing algorithm in standard C++ library. and "remove" or "remove_if".
Hope that this helped
To delete an element use the following way:
// declaring and assigning array1
std:vector<int> array1 {0,2,3,4};
// erasing the value in the array
array1.erase(array1.begin()+n);
For a more broad overview you can visit: http://www.cplusplus.com/reference/vector/vector/erase/
if you need to erase an element inside of a for-loop, do the following:
for(int i = 0; i < vec.size(); i++){
if(condition)
vec.erase(vec.begin() + i);
}
You need to use the Standard Template Library's std::vector::erase function.
Example: Deleting an element from a vector (using index)
// Deleting the eleventh element from vector vec
vec.erase( vec.begin() + 10 );
Explanation of the above code
std::vector<T,Allocator>::erase Usage:
iterator erase (iterator position); // until C++11
iterator erase( const_iterator pos ); // since C++11 and until C++20
constexpr iterator erase( const_iterator pos ); // since C++20
Here there is a single parameter, position which is an iterator pointing to a single element to be removed from the vector.
Member types iterator and const_iterator are random access iterator types that point to elements.
How it works
erase function does the following:
It removes from the vector either a single element (position) or a range of elements ([first, last)).
It reduces the container size by the number of elements removed, which are destroyed.
Note: The iterator pos must be valid and dereferenceable. Thus the end() iterator (which is valid, but is not dereferenceable) cannot be used as a value for pos.
Return value and Complexity
The return value is an iterator pointing to the new location of the element that followed the last element that was erased by the function call. This is the container end of the operation that erased the last element in the sequence.
Member type iterator is a random access iterator type that points to elements.
Here, the time complexity is linear on the number of elements erased (destructions) plus the number of elements after the last element is deleted (moving).
The previous answers assume that you always have a signed index. Sadly, std::vector uses size_type for indexing, and difference_type for iterator arithmetic, so they don't work together if you have "-Wconversion" and friends enabled. This is another way to answer the question, while being able to handle both signed and unsigned:
To remove:
template<class T, class I, class = typename std::enable_if<std::is_integral<I>::value>::type>
void remove(std::vector<T> &v, I index)
{
const auto &iter = v.cbegin() + gsl::narrow_cast<typename std::vector<T>::difference_type>(index);
v.erase(iter);
}
To take:
template<class T, class I, class = typename std::enable_if<std::is_integral<I>::value>::type>
T take(std::vector<T> &v, I index)
{
const auto &iter = v.cbegin() + gsl::narrow_cast<typename std::vector<T>::difference_type>(index);
auto val = *iter;
v.erase(iter);
return val;
}
here is one more way to do this if you want to delete a element by finding this with its value in vector,you just need to do this on vector.
vector<int> ar(n);
ar.erase(remove(ar.begin(), ar.end()), (place your value here from vector array));
it will remove your value from here.
thanks
the fastest way (for programming contests by time complexity() = constant)
can erase 100M item in 1 second;
vector<int> it = (vector<int>::iterator) &vec[pos];
vec.erase(it);
and most readable way :
vec.erase(vec.begin() + pos);
I'm trying to create a function which takes in a vector and simply reverses (manually). I'm aware of the existence of reverse(), but I ran into the "Vector iterator not dereferencable" problem and for educational purposes, I'd like to know what it means. I tried researching this problem and someone (on this forum) said that vect.end() is not dereferencable by definition, but from my understanding, using reverse_iterator is just reversing the ends, so following the logic; vect.rend should not be dereferencable.
vector<int> reverseVector(vector<int>);
int main()
{
vector<int> vec;
for (int i = 0; i < 11; i++)
{
vec.push_back(i);
}
vec = reverseVector(vec);
for (vector<int>::iterator it = vec.begin(); it != vec.end(); it++)
{
cout << *it << " ";
}
cout << endl;
return 0;
}
vector<int> reverseVector(vector<int> vect)
{
vector<int>::reverse_iterator ritr;
for (ritr = vect.rbegin(); ritr != vect.rend(); ritr++)
{
vect.insert(vect.begin(), *ritr);
vect.pop_back();
}
return vect;
}
You are deleting elements from the vector (popping from the back), which invalidates the reverse iterator.
You could just iterate through half of the vector and swap the elements, lke this:
void swap(int& a, int& b) {
int tmp = a;
a = b;
b = tmp;
}
vector<int> reverseVector(vector<int> vect) {
const size_t origin_size = vect.size();
for(size_t i = 0; i < origin_size/2; ++i)
swap(vect[i], vect[origin_size - 1 - i]);
return vect;
}
Your problem has nothing to do with the dereferencability or otherwise of rend(). You're modifying the vector while iterating over it, which invalidates the iterator.
To answer your original question, a reverse_iterator isn't just "reversing the ends" compared to a forward iterator. rbegin() is end() - 1, and rend() is begin() - 1.
If you add an element to the vector, ritr may be invalidated thus the error
Vector iterator not dereferencable.
Thus its better using an index as your loop variable or better a copy(temp) vector for reverse task.
Both insert and pop_back member functions modify the vector and invalidate iterators.
A tip as design-issue: use always const-reference in a function, unless you really know what you are doing. So you will avoid stepping in traps like this. For example:
vector<int> reverseVector(const vector<int> &vect)
Now you wont have this problem, because you can not modify vect.
Doing a representation of a sudoku grid, and using a vector of vectors where each grid is a set. Basically I want there to be vector of vectors to represent the grid. Each square would be a possibility of values from a set (1-9). How would I go about firstly setting the size of the vector? And then how would I print the values from the vector of vectors.
My vector variable:
vector<vector<set<int>>> myVector;
Very important thing in programming is to simplify Your tasks. You must rethink what You want to do, how You want to do it and why use this very solution to solve Your problem.
In Your case (basing on question) there is no need to use such complex, nested containers, just use for example 2 dimmensional array.
About iterationg over collections, You can use for-each loop:
//declaring container with base size 10
std::vector<std::vector<int>> container(5);
//for-each loop, nice way to iterate over collections
for(auto& c: container) {
for(int i = 0; i < 5; i ++) {
c.push_back(i);
}
}
//printing
for(auto& c : container) {
for(auto& v : c) {
std::cout << v << " ";
}
std::cout << std::endl;
}