How to move the later half of a vector into another vector?

折月煮酒 提交于 2019-12-11 04:55:39

问题


I have a vector and I would like to efficiently break out the second half of the vector into another vector using STL algorithms. Here is one way I see to do this, but expect there are more efficient and succinct answers, or at the least, one that uses the stl algorithms:

std::vector<Entry> &entries = someFunction();
int numEntries = entries.size();

// Assume numEntries is greater than or equal to 2.

std::vector<Entry> secondEntries;
std::vector<Entry>::iterator halfway = entries.begin() + numEntries / 2;
std::vector<Entry>::iterator endItr  = entries.end() 

// Copy the second half of the first vector in the second vector:
secondEntries.insert(secondEntries.end(), halfway, endItr);

// Remove the copied entries from the first vector:
entries.erase(halfway, endItr);

回答1:


Taking a step back, keep in mind to make sure that you're working with iterators with your own algorithms, and not (necessarily) containers. So if you have this:

void foo(const std::vector<Entry>& v) { /* ... */ }

And now you're stuck in this situation:

std::vector<Entry> entries = someFunction();

// have to split entries! make more containers? :(
foo(first_half(entries));
foo(second_half(entries));

Consider using iterators instead:

// or a template, if it doesn't hurt
void foo(std::vector<Entry>::const_iterator first, 
         std::vector<Entry>::const_iterator second) { /* ... */ }

So now you denote ranges and not containers:

std::vector<Entry> entries = someFunction();

// easy to split entries! :)
auto middle = entries.begin() + entries.size() / 2;
foo(entries.begin(), middle);
foo(middle + 1, entries.end());

This limits the number of unnecessary containers and allocations you make.


With that out of the way, in C++11 you can do this (rest is the same):

// *Move* the second half of the first vector in the second vector:           
secondEntries.insert(secondEntries.end(),
                        std::make_move_iterator(halfway),
                        std::make_move_iterator(endItr));

If Entry has a move constructor, the move_iterator adapter will ensure that it is used during the insertion (if it doesn't a normal copy is made). In C++03, what you have is probably best.




回答2:


std::move can do a better job if you have access to a c++11 compiler and moveable objects.

Note that you still need to erase them from the first vector.




回答3:


There are several other ways of performing this task for example by using copy algorithm and an insert iterator.

But algorithmic the complexity of these actions will always be O(n) due to the nature of the vector container. Vector is not a list that allows moving big chunks of data from one container to another in a O(1) (constant) time. Depending on the particular STL implemenation one way can be 10-20% better than the other, but unlikely it will be more than that.

If data type of your container allows move semantics and you have these language features available, this will definitely help. But this is more about handling data object in the container rather than the container itself.



来源:https://stackoverflow.com/questions/11938889/how-to-move-the-later-half-of-a-vector-into-another-vector

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!