"Merge" pointer to vector - c++

Sorry if the title is wrong. I am not sure how to describe my problem in a line.
Suppose I have multiple vectors of type cv::Point and that at each iteration I am to create a new vector that will hold the concatenation of 2 other vectors, what is the most efficient way of doing so? In the example below, vector V4 will hold the elements of vector V1 and V2, and V5 will hold V4 and V3.
I would not like to copy the elements over. It would be better if I could get a single iterator that points to V1 and V2 because the vectors get really large over time.
I have tried this from What is the best way to concatenate two vectors? but im not sure if there are faster options. I also used the boost:join function but it seems to be much slower.
Ideally, this copy/move operation is time constant because the entire application revolves around it.
AB.reserve( A.size() + B.size() ); // preallocate memory
AB.insert( AB.end(), A.begin(), A.end() );
AB.insert( AB.end(), B.begin(), B.end() );

You might want to consider doing something at least vaguely like a deque is normally implemented--essentially a vector of pointers to vectors, that keeps track of the bounds on each component vector, so it can find the appropriate vector, the adjust the index for the vector that contains the element you need.
Depending on the situation, you might also consider attempting to keep the component vectors equal in size to speed computation of the correct index. If they start out with wildly disparate sizes, this probably won't be worthwhile, but if they're close to the same, it may be worth moving some over from one to the next to equalize their sizes. To facilitate this, you'd want to leave an initially-unused section at the beginning of each vector so you can move some elements from one to the beginning of the next quickly and easily.

Related

Moving elements between two std::vectors without making copies [duplicate]

How can I move some elements from first vector to second, and the elements will remove from the first?
if I am using std::move, the elements not removed from first vector.
this is the code I wrote:
move(xSpaces1.begin() + 7, xSpaces1.end(), back_inserter(xSpaces2));
Resurrecting an old thread, but I am surprised that nobody mentioned std::make_move_iterator combined with insert. It has the important performance benefit of preallocating space in the target vector:
v2.insert(v2.end(), std::make_move_iterator(v1.begin() + 7),
std::make_move_iterator(v1.end()));
As others have pointed out, first vector v1 is now in indeterminate state, so use erase to clear the mess:
v1.erase(v1.begin() + 7, v1.end());
std::move and std::copy operate on elements, not containers. You have to mutate the container separately. For example, to move the first 17 elements of v1 into a new vector v2:
std::vector<Foo> v1, v2;
// populate v1 with at least 17 elements...
auto it = std::next(v1.begin(), 17);
std::move(v1.begin(), it, std::back_inserter(v2)); // ##
v1.erase(v1.begin(), it);
After line ##, the first 17 elements of v1 are still there, but they've been "moved-from", so they're in an indeterminate state.
The std::move lets you move the objects, as opposed to copying them, allowing for a potentially faster execution speed. The savings may be even greater when you move a range of values. However, when you do move a range from a container, the container still holds the places that were once occupied by these values.
You need to resize the container manually to remove these placeholders if you want to get rid of them (you don't have to, in case you would prefer reusing these container spots for other elements). One way to do it is to call vector::erase on the same range that you moved out of the container.
You can't move elements from one vector to another the way you are thinking about; you will always have to erase the element positions from the first vector.
If you want to change all the elements from the first vector into the second and vice versa you can use swap.
If you want to move the same amount of elements between two vectors, you can use swap_ranges

What is the best way to move a range from a container to another? [duplicate]

How can I move some elements from first vector to second, and the elements will remove from the first?
if I am using std::move, the elements not removed from first vector.
this is the code I wrote:
move(xSpaces1.begin() + 7, xSpaces1.end(), back_inserter(xSpaces2));
Resurrecting an old thread, but I am surprised that nobody mentioned std::make_move_iterator combined with insert. It has the important performance benefit of preallocating space in the target vector:
v2.insert(v2.end(), std::make_move_iterator(v1.begin() + 7),
std::make_move_iterator(v1.end()));
As others have pointed out, first vector v1 is now in indeterminate state, so use erase to clear the mess:
v1.erase(v1.begin() + 7, v1.end());
std::move and std::copy operate on elements, not containers. You have to mutate the container separately. For example, to move the first 17 elements of v1 into a new vector v2:
std::vector<Foo> v1, v2;
// populate v1 with at least 17 elements...
auto it = std::next(v1.begin(), 17);
std::move(v1.begin(), it, std::back_inserter(v2)); // ##
v1.erase(v1.begin(), it);
After line ##, the first 17 elements of v1 are still there, but they've been "moved-from", so they're in an indeterminate state.
The std::move lets you move the objects, as opposed to copying them, allowing for a potentially faster execution speed. The savings may be even greater when you move a range of values. However, when you do move a range from a container, the container still holds the places that were once occupied by these values.
You need to resize the container manually to remove these placeholders if you want to get rid of them (you don't have to, in case you would prefer reusing these container spots for other elements). One way to do it is to call vector::erase on the same range that you moved out of the container.
You can't move elements from one vector to another the way you are thinking about; you will always have to erase the element positions from the first vector.
If you want to change all the elements from the first vector into the second and vice versa you can use swap.
If you want to move the same amount of elements between two vectors, you can use swap_ranges

How to move all the pointers from one vector to another?

Basically what I want to do is remove some of the pointers inside my vector, but I found out that it can be quite slow to do that in the middle of the vector.
So I have a vector that already has data inside:
std::vector<Class*> vec1; // This already contains pointers
I'll iterate through vec1 and will add some of the pointers to another vector (vec2): vec2.push_back(vec1.at(index))
Now I would like to do is something like vec1 = vec2 but I don't know if this is the better (effecient) way to do that.
What would be the best way to do that?
I tried:
While looping through vec1 simply erasing what I need to remove from it:
it = vec1.erase(it)
While looping through vec1 moving the last item to the actual index and poping_back
vec1.at(index) = vec1.back();
vec1.pop_back();
Setting some attribute on the object the pointer is pointing while looping through vec1 and than using std::remove_if
vec1.erase(std::remove_if(vec1.begin(), vec1.end(), shouldBeRemoved), vec1.end());
Now I'm trying to generate a new vector while looping through vec1 and adding the pointers I want to keep, then "swapping" or "moving" the contents of this new vector to vec1.
Apparently when doing it the 4th way, the pointers get invalidated :(
I would love to see what you guys suggest me. A big thank you to everyone that is willing to help!
You can just use std::remove_if to conditionally remove items from a vector. This algorithm will shift items that need to be kept over to the front. Follow it up with a std::vector::erase call to actually remove the items not shifted to the front.
This is similar to your option 3, but you don't need to set an attribute first - just use a predicate that determines if the item should be kept or not, and avoid having to pass over the vector twice.
If you don't want to do it in-place, but want to fill a new vector, then std::copy_if does that.
Removing things from a vector should be done with the erase remove idiom
It is well covered here: https://en.wikipedia.org/wiki/Erase%E2%80%93remove_idiom
The basic idea is to shift the elements first and then erase the unneeded items which is faster than erasing and shifting each individual element which is done as from the example with:
v.erase( std::remove( v.begin(), v.end(), 5 ), v.end() );
But in general: If you have a lot of add/erase steps in your algorithm, you should use a std::list where removing elements in the middle is much cheaper at all.
Your attempt #2 suggests that you're not interested in the order of the elements. remove_if will suffer performance problems as it will maintain the order of the items that you don't delete; meaning you could do a substantial number of shifts to maintain this order.
The swapping and popping will suffer the problem that repeatedly popping the back isn't required - it could resize the vector or do other things.
As such, by combining the ideas - of swapping the "last not swapped out" (ie last the first time, 2nd last the 2nd etc) and then at the end erasing the end items once complete; you should have the fastest algorithm.
Some of the comments suggest that a copy is faster than a swap; and while true when doing a single copy; for a vector when you're copying multiple elements multiple times; the swap will be significantly faster.

Does inserting an element in vector by re-sizing the vector every time takes more time?

I got a decision making problem here. In my application, I need to merge two vectors. I can't use stl algorithms since data order is important (It should not be sorted.).
Both the vectors contains the data which can be same sometimes or 75% different in the worst case.
Currently I am confused b/w two approaches,
Approach 1:
a. take an element in the smaller vector.
b. compare it with the elements in bigger one.
c. If element matches then skip it (I don't want duplicates).
d. If element is not found in bigger one, calculate proper position to insert.
e. re-size the bigger one to insert the element (multiple time re-size may happen).
Approach 2:
a. Iterate through vectors to find matched element positions.
b. Resize the bigger one at a go by calculating total size required.
c. Take smaller vector and go to elements which are not-matched.
d. Insert the element in appropriate position.
Kindly help me to choose the proper one. And if there is any better approach or simpler techniques (like stl algorithms), or easier container than vector, please post here. Thank you.
You shouldn't be focusing on the resizes. In approach 1, you should use use vector.insert() so you don't actually need to resize the vector yourself. This may cause reallocations of the underlying buffer to happen automatically, but std::vector is carefully implemented so that the total cost of these operations will be small.
The real problem with your algorithm is the insert, and maybe the search (which you didn't detail). When you into a vector anywhere except at the end, all the elements after the insertion point must be moved up in memory, and this can be quite expensive.
If you want this to be fast, you should build a new vector from your two input vectors, by appending one element at a time, with no inserting in the middle.
Doesn't look like you can do this in better time complexity than O(n.log(n)) because removing duplicates from a normal vector takes n.log(n) time. So using set to remove duplicates might be the best thing you can do.
n here is number of elements in both vectors.
Depending on your actual setup (like if you're adding object pointers to a vector instead of copying values into one), you might get significantly faster results using a std::list. std::list allows for constant time insertion which is going to be a huge performance overhead.
Doing insertion might be a little awkward but is completely do-able by only changing a few pointers (inexpensive) vs insertion via a vector which moves every element out of the way to put the new one down.
If they need to end up as vectors, you can then convert the list to a vector with something like (untested)
std::list<thing> things;
//efficiently combine the vectors into a list
//since list is MUCH better for inserts
//but we still need it as a vector anyway
std::vector<thing> things_vec;
things_vec.reserve(things.size()); //allocate memory
//now move them into the vector
things_vec.insert(
things_vec.begin(),
std::make_move_iterator(things.begin()),
std::make_move_iterator(things.end())
);
//things_vec now has the same content and order as the list with very little overhead

Removing Vector from 2D vector

I have a 2D vector containing 96 blocks of 600 values, which is what I want.
I need to remove (blocks) that do not contain sufficient energy. I have managed to calculate the energy but do not know which way would be better in removing the (blocks) that do not contain enough energy.
In your opinions would it be better to create a temporary 2D vector, that pushed back the blocks that do contain enough energy and then delete the original vector from memory or...
Should I remove the blocks from the vector at that particular position?
I'm assuming you have this:
typedef std::vector<value> Block;
typedef std::vector< Block > my2dVector;
and you have a function like this:
bool BlockHasInsufficientEnergy( Block const& vec );
and you want to remove the Blocks that do not have sufficient energy.
By remove, do you mean you want there to be fewer than 96 Blocks afterwards? I will assume so.
Then the right way to do this is:
void RemoveLowEnergyBlocks( my2dVector& vec )
{
my2dVector::iterator erase_after = std::remove_if( vec.begin(), vec.end(), BlockHasInsufficientEnergy );
vec.erase( erase_after, vec.end() );
}
the above can be done in one line, but by doing it in two what is going on should be more clear.
remove_if finds everything that passes the 3rd argument condition, and filters it out of the range. It returns the point where the "trash" at the end of the vector lives. We then erase the trash. This is called the remove-erase idiom.
Maybe you'd want to use linked list, or just set filtered-out items as NULL's, or mark them with bool member flag, or keep a separate vector of indexes of filtered items (if you have several filters at once this saves memory).
The solution vary on what are the constraints. Do you need random access? How much object copy takes? Etc.
Also you can take a look at the STL code (this is STL's vector, right?) and check if it does what you ask for - i.e. copying a vector data.
It depends, in part, on how you define better in this case. There may be advantages to either method, but it would be hard to know exactly what they are. Most likely, it is probably somewhat "better", in terms of memory and processing performance, to erase the exact positions you don't want from the vector instead of allocating an entirely new one.
It may be better still to consider using a deque or list for that purpose, since they may avoid large reallocations that the vector is likely to make as it tries to keep a contiguous segment of memory.