Is there an easy and run-time efficient way to take a std::vector<> in c++ and split it in half into two other vectors?
Because right now I'm doing this:
std::vector<> v1, v2;
for(int i = 0; i < vector.size(); i++)
{
if(i < vector.size()/2) v1.push_back(vector[i]);
else v2.push_back(vector[i]);
}
which runs in O(n) time and this is an operation I have to perform quite frequently. So is there a better way?
If you really need 2 vectors, and you can't use GMan's suggestion in the comments:
// where v1 is your original vector
std::vector<T> v2(
std::make_move_iterator(v1.begin() + v1.size()/2),
std::make_move_iterator(v1.end()));
v1.erase(v1.begin() + v1.size()/2, v1.end());
It's still O(n), but you can't do any better than that.
If you need to keep the original vector separate:
std::vector<T> v2(v1.begin(), v1.begin() + v1.size()/2),
v3(v1.begin() + v1.size()/2, v1.end());
Related
I currently have a vector and need to find the n largest numbers in it. For example, a user enters 5, i gotta run through it and output the 5 largest. Problem is, i can not sort this vector due to other constraints. Whats the best way to go about this?
Thanks!
Based on your description of not modifying the original vector and my assumption that you want the order to matter, I suggest std::partial_sort_copy:
//assume vector<int> as source
std::vector<int> dest(n); //largest n numbers; VLA or std::dynarray in C++14
std::partial_sort_copy(
std::begin(source), std::end(source), //.begin/.end in C++98/C++03
std::begin(dest), std::end(dest),
std::greater<int>() //remove "int" in C++14
);
//output dest however you want, e.g., std::copy
Is copying and sorting an option? I mean if your application is not that performance critical, this is the simplest (and asymptotically not too bad) way to go!
Something like this (A is incoming vector, N the number largest you want to find, v becomes the result vector):
vector<T> v(N, 0);
for each element in A:
if (element > v[N-1])
for(i = N-1; i > 0 && v[i] < element; i--)
v[i] = v[i-1];
v[i] = element;
This is some sort of "pseudo-C++", not exactly C++, but hopefully describes how you'd do this.
In C++, if I have two vectors of int:
A = [1, 2, 3 ,4];
B = [1, 2, 3, 4];
How can I merge them into one vector of pairs:
[(1,1), (2,2), (3,3), (4, 4)]
Of course I can do that with a loop. But can we do that using suitable STL functions and iterators?
You can use an algorithm for this:
std::vector<std::pair<int, int>> target;
target.reserve(A.size());
std::transform(A.begin(), A.end(), B.begin(), std::back_inserter(target),
[](int a, int b) { return std::make_pair(a, b); });
I agree that Dietmar Kühl's answer does exactly what was asked in the question, but I also agree with Kakadur's comment. A loop is hidden in std::transform() so the complexity is the same. Some people will judge, but if there is no direct proof of one way being better than the other, I tend to choose the most readable and least verbose version:
// create a vector of length of the smaller vector
std::vector<std::pair<int, int>> target( A.size() < B.size() ? A.size() : B.size() );
for (unsigned i = 0; i < target.size(); i++)
target[i] = std::make_pair(A[i], B[i]);
P.S.
The code above allocates just enough space for the target vector, so that the potential overhead of push_back (in case of reallocation) can be avoided.
I am trying to do the following mathematical operation with two vectors:
v1 = [a1][a2][a3][a4][a5]
v2 = [b1][b2][b3][b4]b5]
Want to compute:
v = [a2*b2][a3*b3][a4*b4][a5*b5]
Note that I did not want the first element in the new vector.
I was wondering if there is a more efficient (one-liner) way to multiply (element-wise) two vectors in c++ than a for-loop (using push back). My current approach is as follows,
for(long i=1;i < v1.size();++i){
v.push_back(v1[i]*v2[i]);
}
I also tried the following,
for (long i = 1; i < v1.size(); ++i){
v[i-1] = v1[i]*v2[i];
}
Any suggestions?
std::transform( v1.begin()+1, v1.end(),
v2.begin()+1, v.begin(), // assumes v1,v2 of same size > 1,
// v one element smaller
std::multiplies<int>() ); // assumes values are 'int'
You can replace v.begin() with std::back_inserter(v) if v is empty, you should reserve() memory upfront to avoid multiple allocations.
You could look into std::valarray. It's designed to allow mathematical operations on every element in the array.
I have
vector<int> my_vector;
vector<int> other_vector;
with my_vector.size() == 20 and other_vector.size() == 5.
Given int n, with 0 < n < 14, I would like to replace the subvector (my_vector[n], myvector[n+1], ..., myvector[n+4]) with other_vector.
For sure with the stupid code
for(int i=0; i<5; i++)
{
my_vector[n+i] = other_vector[i];
}
I'm done, but I was wondering if is there a more efficient way to do it. Any suggestion?
(Of course the numbers 20 and 5 are just an example, in my case I have bigger size!)
In C++11, a friendly function std::copy_n is added, so you can use it:
std::copy_n(other_vector.begin(), 5, &my_vector[n]);
In C++03, you could use std::copy as other answers has already mentioned.
You could use std::copy:
// Get the first destination iterator
auto first = std::advance(std::begin(my_vector), n);
// Do the copying
std::copy(std::begin(other_vector), std::end(other_vector), first);
Although this basically is the same as your naive solution.
I dont know about performance, but a cleaner version would be to use std::copy
std::copy(other_vector.begin(),other_vector.end(),my_vector.begin()+n);
For min-max performance, perhaps(?) memcpy is the answer..
memcpy(my_vector.begin()+n, other_vector.begin(), sizeof(int) *other_vector.size());
Say I have a vector / list whatever of ints populated with 2300 values
I want to be able to easily slice this into 4 vectors /lists (not necessarily of equal size).
e.g.
vec1 ( elements 0 - 500 )
vec2 ( elements 501 - 999)
vec3 ( elements 1001 - 1499)
etc.
A common way to do it would be to use the one container, and just define separate iterator ranges over it.
std::vector<int> vec(2300);
it0 = vec.begin();
it1 = vec.begin() + 500;
it2 = vec.begin() + 1000;
it3 = vec.begin() + 1500;
it4 = vec.begin() + 2000;
it5 = vec.end();
Now, the first range is simply defined by the iterators it0 and it1. The second by it1 and it2, and so on.
So, if you want to apply a function to every element in the third range, you'd simply do this:
std::for_each(it2, it3, somefunc);
Actually copying the elements into separate containers may be unnecessary, and would carry a performance cost.
std::list would be the best choice, as you just build lists by joining pointers. Finding the exact place to slice would be the problem, though, because you have to reach that point in the list iterator to make the cut.
EDIT:
As per comments (thanks for the insights), maybe using std::vector<int> and iterators is a good idea. However, with plain iterators, you loose the length of the vector, so I propose using, for instance, a boost::range_iterator:
std::vector<int> vec(2300);
it0 = vec.begin();
it1 = vec.begin() + 500;
it2 = vec.begin() + 1000;
it3 = vec.begin() + 1500;
it4 = vec.begin() + 2000;
it5 = vec.end;
typedef boost::iterator_range< std::vector<int>::iterator > my_slice_t;
my_slice_t slice1 = boost::make_iterator_range(it0, it1);
...
Then, you can use slice1 as a normal, underlying std::vector<int> as per iteration:
std::for_each(slice1.begin(), slice1.end(), /* stuff */);
See the fourth std::vector<> constructor documented here.
// given std::vector<T> vec with 2300 elements
std::vector<T> vec1(vec.begin(), vec.begin() + 500);
std::vector<T> vec2(vec.begin() + 500, vec.begin() + 1000);
std::vector<T> vec3(vec.begin() + 1000, vec.begin() + 1500);
std::vector<T> vec4(vec.begin() + 1500, vec.begin() + 2000);
std::vector<T> vec5(vec.begin() + 2000, vec.end());
Actually it is doable with the vector container
#include <vector>
#include <iostream>
using namespace std ;
int main()
{
vector<int> ints ;
vector<int> ints_sliced;
int i ;
// populate
for( i = 0 ; i < 100 ; i++ )
ints.push_back(i) ;
// slice from 10-19
ints_sliced.insert(ints_sliced.begin(), ints.begin()+10, ints.begin()+20) ;
// inspect
vector<int>::iterator it ;
for( it = ints_sliced.begin() ; it != ints_sliced.end() ; it++ )
cout << *it << endl ;
}
Oh, if you happen to be using g++ and GNU stdlibc++, you can use roughly
g++ -march=native -O3 -ftree-vectorize ...
If you also throw in GNU OpenMP support (libgomp) you can benefit (evaluate, profile!) from automatic parallelization of standard algorithms,
g++ -D_GLIBCXX_PARALLEL -fopenmp -march=native -O3 .... -lgomp
YMMV - I wanted to just throw this out there, because e.g. the parallel for_each seems to be close to what you want (but, automagic and self-adapting to container size, iterator type and number of processors)
In addition to #jalf's correct observation that actually copying the subvectors into fresh vectors might be a waste of time and space, let me point at valarray.
Intro: valarray
Valarray may be more complicated, but especially in the face of parallel processing, might lead to better ways to subvector work for the different threads. Things to look for:
algorithmic pre-science (if locations in a certain pattern have a certain property (e.g. are known to be zero), you can hand it to an optimized worker for those values)
subvector alignment (the aligment can make or break the availability of SIMD, SSE4 optimized versions; have a look at gcc -ftree-vectorizer for more background)
Now valarrays have quite a number of 'obscure' operations and tricks to them (gslices; basically revectored array dimensions to address the original array) that I won't go into here, but suffice it to say, if you want to do number crunching across subsets of contiguous arrays of (mainly) floating points[1], it will pay to read up on those.
Mandatory (braindead) teaser
// mask_array example
#include <iostream>
#include <valarray>
using namespace std;
int main ()
{
valarray<int> myarray (10);
for (int i=0; i<10; ++i) myarray[i]=i; // 0 1 2 3 4 5 6 7 8 9
valarray<bool> mymask (10);
for (int i=0; i<10; ++i)
mymask[i]= ((i%2)==1); // f t f t f t f t f t
myarray[mymask] *= valarray<int>(10,5); // 0 10 2 30 4 50 6 70 8 90
myarray[!mymask] = 0; // 0 10 0 30 0 50 0 70 0 90
cout << "myarray:\n";
for (size_t i=0; i<myarray.size(); ++i)
cout << myarray[i] << ' ';
cout << endl;
return 0;
}
This was copied verbatim from the above link, you will want to adapt to your specific need. There was probably a good reason why you kept the endgoal a bit vague, so I'll happily leave the rest of the work to you!
Wrapup
If you really want to go all the way, however, you should start looking at the big guns (Blitz++, et al.).
[1] these have historically been the focus for vectorized CPU instruction sets. However, als #jalf notes, SSE2 and higher includes SIMD integer instructions as well