I need to reserve x number of elements in a std::vector, say 10. Then I need to write some y number of values into it, say 5 (most of the time y < x). Is there a way to say how many values have been written to it and how may are still available?
Example:
Say I allocate 10 elements
std::vector<int> v(10);
But I only fill 7 of these elements
for (unsigned i = 0; i<7; i++)
v[i] = i;
How can I tell that 7 elements have been filled and I still have 3 available?
I tried running
v.size() and v.capacity() but both return 10.
Do you mean something like this?
std::vector<int> a; // dont allocate anything
// allocate memory for 10 elements,
// but dont actually create them. a.size() is still 0.
a.reserve(10);
for(std::size_t i = 0; i < 7; ++i) {
// copy i to a new element at the back
// of the vector. This will never reallocate
// memory, as long as at most 10 elements
// are pushed:
a.push_back(i);
}
// a.size() is now 7
Edit: I added a method using std::unique_ptr.
If C++17 is available to you, how about replacing v's elements by std::optional<int> as follows ?
#include <iostream>
#include <optional>
#include <vector>
#include <algorithm>
int main()
{
std::vector<std::optional<int>> v(10);
for (std::size_t i = 0; i<7; ++i){
v[i] = i;
}
std::cout
<< (v.size() - std::count(v.cbegin(), v.cend(), std::nullopt))
<< " elements have been filled and I still have "
<< std::count(v.cbegin(), v.cend(), std::nullopt)
<< " available."
<< std::endl << std::endl;
for(const auto v_i : v)
{
if(v_i.has_value()){
std::cout << v_i.value() << " ";
}
}
return 0;
}
But if you are constrained by an older version, I think that std::unique_ptr would be a solution.
DEMO:
#include <iostream>
#include <memory>
#include <vector>
#include <algorithm>
int main()
{
std::vector<std::unique_ptr<int>> v(10);
for (std::size_t i = 0; i<7; ++i){
v[i] = std::make_unique<int>(i);
}
std::cout
<< (v.size() - std::count(v.cbegin(), v.cend(), nullptr))
<< " elements have been filled and I still have "
<< std::count(v.cbegin(), v.cend(), nullptr)
<< " available."
<< std::endl << std::endl;
for(const auto& v_i : v)
{
if(v_i){
std::cout << *v_i << " ";
}
}
return 0;
}
Finally, I found similar approaches here.
I need to reserve x number of elements in a std::vector, say 10.
std::vector has a reserve() method for that exact purpose.
Then I need to write some y number of values into it, say 5 (most of the time y < x). Is there a way to say how many values have been written to it and how may are still available?
The vector's capacity() is the number of elements have been allocated total, whereas its size() is the number of allocated elements that have been populated with values. So, capacity() - size() is the number of available elements that have been allocated but not assigned.
I tried running v.size() and v.capacity() but both return 10.
That is because you are calling the vector constructor that allocates AND populates elements at the same time. You are creating a vector named v that has 10 elements populated with 0. That is why size() and capacity() are both 10. None of the constructors will do what you want. You need to use the default constructor and then call reserve() separately, eg:
std::vector<int> v;
v.reserve(10); // capacity = 10
for (int i = 0; i < 7; ++i)
v.push_back(i);
size_t filled = v.size(); // size = 7
size_t available = v.capacity() - v.size(); // available = 3
Related
I have a vector in which i save coordinates.
I perform a series of calculations on each coordinate, thats why i have a limit for the vector size.
Right now i clear the vector, when the limit is reached.
I'm searching for a method, that let's me keep the previous values and only erases the very first value in the vector.
Simplified, something like this (if the maximum size of the vector would be 4).
vector<int> vec;
vec = {1,2,3,4}
vec.push_back(5);
vec = {2,3,4,5}
Is this possible?
As suggested by #paddy, you can use std::deque, it is most performant way to keep N elements if you .push_back(...) new (last) element, and .pop_front() first element.
std::deque gives O(1) complexity for such operations, unlike std::vector which gives O(N) complexity.
Try it online!
#include <deque>
#include <iostream>
int main() {
std::deque<int> d = {1, 2, 3, 4};
for (size_t i = 5; i <= 9; ++i) {
d.push_back(i);
d.pop_front();
// Print
for (auto x: d)
std::cout << x << " ";
std::cout << std::endl;
}
}
Output:
2 3 4 5
3 4 5 6
4 5 6 7
5 6 7 8
6 7 8 9
I think you should properly encapsulate this behaviour in your own vector class, as a std::vector wrapper. You could pass the max capacity as an argument to your constructor. And you could reimplement the methods that may cause "overflow" while just reusing the std::vector ones for the others.
To simplify what you pretend to achieve for the push_back case, using a function and a global variable, you could:
check against a max capacity and,
if that capacity is already reached, rotate your vector contents left by one position; then simply overwrite the last element;
otherwise do a normal push_back.
[Demo]
#include <algorithm> // rotate
#include <iostream> // cout
#include <vector>
const size_t max_capacity{4};
void push_back(std::vector<int>& v, int n)
{
if (v.size() == max_capacity)
{
// Rotate 1 left
std::rotate(std::begin(v), std::begin(v) + 1, std::end(v));
v[v.size() - 1] = n;
}
else
{
v.push_back(n);
}
}
int main()
{
std::vector<int> v{};
for (auto i{1}; i < 9; i++)
{
push_back(v, i);
for (auto&& n : v) { std::cout << n << " "; }
std::cout << "\n";
}
}
This question already has answers here:
Choice between vector::resize() and vector::reserve()
(4 answers)
Why can't you access memory allocated by vector::reserve
(3 answers)
Closed 3 years ago.
I am just trying to learn STL for Competitive programming and stuck with this doubt!
1. When i use vector::reserve(n) my loops labeled as loop1 and loop2 don't print anything.
2. but when i use vector::assign(n,0) my loops labeled as loop 1 and loop 2 works fine.
why is it so?
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;
int main()
{
int test;
scanf("%d", &test);
while (test > 0) {
int n;
scanf("%d", &n);
vector<int> arr;
arr.reserve(n);
//arr.assign(n,0);
for (int i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
sort(arr.begin(), arr.end());
vector<int>::iterator itr;
// loop1
for (int x : arr) {
printf("%d ", x);
}
//loop2
for (itr = arr.begin(); itr != arr.end(); itr++) {
printf("%d ", *itr);
}
test--;
}
return 0;
}
This is a common mistake. std::vector::reserve does not create elements or change the size of the container; you're actually causing undefined behavior. reserve changes just the capacity. You are looking for std::vector::resize to change the size. Here's an example for clarity:
#include <iostream>
#include <vector>
int main() {
std::vector<int> ivec;
std::cout << ivec.size() << " - " << ivec.capacity() << '\n'; // 0 - 0
ivec.reserve(100);
std::cout << ivec.size() << " - " << ivec.capacity() << '\n'; // 0 - 100
ivec.resize(30);
std::cout << ivec.size() << " - " << ivec.capacity() << '\n'; // 30 - 100
}
vector::reserve doesn't change the size of the vector. Instead, it just allocates additional memory, increasing the capacity of the vector for operations such as push_back.
For example:
std::vector<int> v;
// v.size() == 0, v.capacity() == 0
for(int i = 0; i < 100; i++) {
v.push_back(i); // This will resize the vector a few times
}
// v.size() == 100, v.capacity() >= 100
Versus
std::vector<int> v;
v.reserve(100);
// v.size() == 0, BUT v.capacity() >= 100
for(int i = 0; i < 100; i++) {
v.push_back(i); // This won't resize the vector now
}
If you want to change the size of the vector, use vector::resize.
I am trying to remove the duplicate elements in a sorted vector such that each element appears only once.
My code:
#include <iostream>
#include <vector>
using namespace std;
void removeDuplicates(vector<int> &nums)
{
vector<int>::iterator it;
unsigned int j = 1;
while(j < nums.size()-1)
{
if(nums.at(j) == nums.at(j-1))
{
it = nums.begin()+j;
nums.erase(it);
--j; // for every removal, correct the index
}
j += 1; // increment the index
}
}
int main ()
{
vector <int> vect;
int arr[] = {0,0,1,1,1,1,1,2,2,3,3,4}; // the given array
int arrSize = sizeof(arr)/sizeof(arr[0]);
for (int i = 0; i <= arrSize-1; i++) // assign values to the vector
{
vect.push_back(arr[i]);
}
removeDuplicates(vect);
cout << "The unique vector elements are: ";
for (int i = 0; i < vect.size(); i++)
{
cout << vect[i] << " ";
}
cout << endl;
return 0;
}
When I run the code, the output is
The vector unique elements are: 0 1 2 3 4
The question gives the following instruction:
Do not allocate extra space for another array, you must do this by
modifying the input array in-place with O(1) extra memory.
In my code, the Big O time complexity is O(n).
How can I remove the duplicates in-place with an extra memory of O(1)?
How can remove the duplicates in-place with a time complexity of O(1)?
You can't. Even with the vector sorted, you simply must compare every single element to know whether it is unique or not. O(N) is optimal.
However, O(1) time complexity wasn't required by the task either:
... with O(1) extra memory.
There was no mention of time complexity constraint - only space complexity.
The simplest way to get rid of duplicates is to use what's already available in the standard library:
nums.erase(std::unique(nums.begin(), nums.end()), nums.end());
You can implement it in place (no extra memory) with a complexity O(n) by simply using two indices, one for reading the elements and one for writing.
#include <iostream>
#include <vector>
void removeDuplicates(std::vector<int> &nums)
{
unsigned int j = 1;
for (unsigned int i = 1; i < nums.size(); i++)
{
if(nums.at(i) != nums.at(i-1))
{
nums.at(j++) = nums.at(i);
}
}
nums.resize(j);
}
int main ()
{
std::vector <int> vect;
int arr[] = {0,0,1,1,1,1,1,2,2,3,3,4}; // the given array
int arrSize = sizeof(arr)/sizeof(arr[0]);
for (int i = 0; i <= arrSize-1; i++) // assign values to the vector
{
vect.push_back(arr[i]);
}
removeDuplicates(vect);
std::cout << "The unique vector elements are: ";
for (int i = 0; i < vect.size(); i++) {
std::cout << vect[i] << " ";
}
std::cout << "\n";
return 0;
}
I would like to check the size of different vectors by iteration using a for loop.
#include <vector>
#include <iostream>
using namespace std;
vector<int> V1;
vector<int> V2;
vector<int> V3;
for (int i=0;i<3;i++){
cout<<Vi.size()<<endl;
}
Unfortunately i don't know if it's possible to iterate through vector names and if it is, how to write the parameter i such that my compiler knows that it is the integer of my loop.
thanks in advance.
There is no way to do what you're attempting to do in that specific way, aka evaluating i into its value for the variable name in Vi.size(), because the compiler evaluates this to a variable named Vi which doesn't exist. However, as others have pointed out you can do this differently but still get the same result, here are a few examples:
Credit to #kerrek-sb for this one (probably the best option):
for (auto* v : {&V1, &V2, &V3}) { std::cout << v->size() << std::endl; }
Using an array (downside: to add more vectors you have to use dynamic allocation and copying; upside: simple for your purposes as shown):
const int size = 3; // Or whatever size you want
// needs to be const because c++11 and up don't support variable length arrays(VLAs)
std::vector<int> V[size];
V[0].push_back(0); // Appends integer to vector
V[0].push_back(10);
V[1].push_back(1);
V[2].push_back(2);
for (int i = 0; i < size; i++) {
std::cout << V[i].size() << std::endl;
} // OUTPUT:
// 2
// 1
// 1
Using an array of pointers to already created vectors(downside: you have to use dynamic allocation to change the size of the array; upside: you can pass vectors into a function and access them like this:
const int size = 3;
std::vector<int> V1(10); // Create three vectors of different sizes
std::vector<int> V2(12);
std::vector<int> V3(14);
std::vector<int> *V[size]; // Create an array of 3 vector<int> pointers
V[0] = &V1; // Set each element to it's corresponding vector
V[1] = &V2;
V[2] = &V3;
for (int i = 0; i < size; i++) {
std::cout << V[i]->size() << std::endl;
} // OUTPUT:
// 10
// 12
// 14
Using a vector of vectors (upside: you can push_back(append) as many vector's as you'd like after creation):
int size = 3; // Or whatever size you want
std::vector<std::vector<int>> V(0);
for (int i = 0; i < size; i++) {
V.push_back(std::vector<int>((i+1)*2)); // (0+1)*2; (1+1)*2; (2+2)*2
}
for (int i = 0; i < V.size(); i++) {
std::cout << V[i].size() << std::endl;
} // OUTPUT:
// 2
// 4
// 6
You could also do a vector of pointers to vector's which would give you both the variable size of a vector and the ability to pass in vectors that are already created from other places.
I want to shift left array values if my v=4 is in a[n],remove 4 from a[n] and at the end index add 0,how i can do this?
#include <iostream>
using namespace std;
const int n=5;
int main()
{
int a[n]={1,5,4,6,8}, v=4;
int b[n];
cout << "Enter a Value" << endl;
cout<<v<<endl;
for(int i=0; i<n; i++){
cout<<a[i];
}
cout<<endl;
for(int j=0; j<n; j++){
b[j]=a[j];
if(a[j]==v)
b[j]=a[++j];
cout<<b[j];
}
return 0;
}
#include <vector> // needed for vector
#include <algorithm> // needed for find
#include <iostream> // needed for cout, cin
using namespace std;
// Vectors are just like dynamic arrays, you can resize vectors on the fly
vector<int> a { 1,5,4,6,8 }; // Prepare required vector
int v;
cout << "enter value"; // Read from user
cin >> v;
auto itr = find( a.begin(), a.end(), v); // Search entire vector for 'v'
if( itr != a.end() ) // If value entered by user is found in vector
{
a.erase(itr); // Delete the element and shift everything after element
// Toward beginning of vector. This reduces vector size by 1
a.push_back(0); // Add 0 in the end. This increases vector size by 1
}
for( int i : a ) // Iterate through all element of a (i holds element)
cout << i; // Print i
cout << '\n'; // Line end
a few helpful links:
vector , find , iterator , erase , push_back
You could use std::rotate. I suggest that you use std::vector instead of C arrays and take full advantage of the STL algorithms. Nevertheless, below I'm illustrating two versions one with C arrays and one with std::vector:
Version with C array:
#include <iostream>
#include <algorithm>
int main()
{
int const n = 5;
int a[n] = {1,5,4,6,8};
std::cout << "Enter a Value" << std::endl;
int v;
std::cin >> v;
for(auto i : a) std::cout << i<< " ";
std::cout << std::endl;
auto it = std::find(std::begin(a), std::end(a), v);
if(it != std::end(a)) {
std::rotate(it + 1, it, std::end(a));
a[n - 1] = 0;
}
for(auto i : a) std::cout << i<< " ";
std::cout << std::endl;
return 0;
}
Version with vector:
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
std::vector<int> a{1,5,4,6,8};
std::cout << "Enter a Value" << std::endl;
int v;
std::cin >> v;
for(auto i : a) std::cout << i<< " ";
std::cout << std::endl;
auto it = std::find(std::begin(a), std::end(a), v);
if(it != std::end(a)) {
std::rotate(it + 1, it, std::end(a));
a.back() = 0;
}
for(auto i : a) std::cout << i<< " ";
std::cout << std::endl;
return 0;
}
Here's an example using std::array
#include <array>
#include <algorithm>
// defines our array.
std::array<int, 5> a = {{ 1, 2, 3, 4, 5 }};
// find the position of the element with the value 4.
auto where = std::find(a.begin(), a.end(), 4);
// if it wasn't found, give up
if (where == a.end())
return 0;
// move every element past "where" down one.
std::move(where + 1, a.end(), where);
// fill the very last element of the array with zero
a[ a.size() - 1] = 0;
// loop over our array, printing it to stdout
for (int i : a)
std::cout << i << " ";
std::cout << "\n";
Why would anyone use these awkward algorithms? Well, there are a few reasons. Firstly, they are container-independant. This will work with arrays and vectors and deques, no problem. Secondly, they can be easily used to work with a whole range of elements at once, not just single items, and can copy between containers and so on. They're also type-independant... you acn have an array of strings, or an vector of ints, or other more complex things, and the algorithms will still work just fine.
They're quite powerful, once you've got over their initial user-unfriendliness.
You can always use either std::array or std::vector or whatever without using the standard library algorithms, of course.
std::array<int, 5> a = {{ 1, 2, 3, 4, 5 }};
size_t where = 0;
int to_remove = 4;
// scan through until we find our value.
while (a[where] != to_remove && where < a.size())
where++;
// if we didn't find it, give up
if (where == a.size())
return 0;
// shuffle down the values
for (size_t i = where; i < a.size() - 1; i++)
a[i] = a[i + 1];
// set the last element to zero
a[ a.size() - 1] = 0;
As a final example, you can use memmove (as suggested by BLUEPIXY) to do the shuffling-down operation in one function call:
#include <cstring>
if (where < a.size() - 1)
memmove(&a[where], &a[where + 1], a.size() - where);