我正在使用一些类和几个使用std :: vector的实用程序方法。
现在我需要在其中一个类上使用pop_front - push_back方法的每一帧(但它们都是链接的,并且一起工作所以我不能只更改一个)。
大多数操作都是遍历所有元素和push_back操作,所以我应该做的最好的工作是:分叉这些类和实用程序的存储库,模板化所有内容并使用deque或list。
但是这意味着大量的代码重写和大量的测试会让我错过截止日期。
所以我需要建议将高效的pop_front写入静态大小的向量(大小不会改变)。
我找到了here的方式:
template<typename T>
void pop_front(std::vector<T>& vec)
{
vec.front() = vec.back();
vec.pop_back();
vec.front() = vec.back(); // but should this work?
}
另一个想法应该是:
template<typename T>
void pop_front(std::vector<T>& vec, already_allocated_vector vec1)
{
vec1.clear();
copy(vec.begin(), vec.end()-1, vec1.begin());
copy(vec1.begin(), vec1.end(), vec.begin());
}
这两种解决方案的速度有多快?还有其他解决方案吗?
答案 0 :(得分:26)
我希望:
template<typename T>
void pop_front(std::vector<T>& vec)
{
assert(!vec.empty());
vec.front() = std::move(vec.back());
vec.pop_back();
}
是最有效的方法,但它不能保持向量中元素的顺序。
如果您需要维护vec
中剩余元素的顺序,您可以执行以下操作:
template<typename T>
void pop_front(std::vector<T>& vec)
{
assert(!vec.empty());
vec.erase(vec.begin());
}
vec
中的元素数量会有线性时间,但这是您在不更改数据结构的情况下可以做到的最佳时间。
这两个函数都不会将vector
保持为常量,因为pop_front
操作按照定义从容器中删除元素。
答案 1 :(得分:6)
由于pop_front()
仅删除第一个元素,因此直接实现如下:
template <typename V>
void pop_front(V & v)
{
assert(!v.empty());
v.erase(v.begin());
}
现在不要担心速度。如果您想返回并优化代码,请询问专用项目时间。
答案 2 :(得分:4)
您也可以像数组一样具有快速恒定时间访问操作的IgushArray(https://github.com/igushev/IgushArray),但插入/擦除操作只需要O(N ^ 1/2)时间。因此,在您的情况下,插入到开头将非常有效。注意,结构对reserve()非常敏感。
template <class T>
void pop_front(IgushArray<T>& v)
{
if (!v.empty())
v.erase(v.begin());
}
在您写的第一个选项中,您违反了元素的顺序。这是一个问题吗?
如果是这样,请使用我写的变体。
如果没有,元素的顺序根本不重要,可能最好使用std :: set或std :: multiset。
答案 3 :(得分:1)
如果您只是尝试擦除第一个元素,那么在函数中使用:
if (my_vector.size()){ //check if there any elements in the vector array
my_vector.erase(my_vector.begin()); //erase the firs element
}
如果你想为整个矢量数组模拟pop front(你希望从头到尾保持弹出每个元素),我建议:
reverse(my_vector.begin(),my_vector.end()); // reverse the order of the vector array
my_vector.pop_back(); // now just simple pop_back will give you the results
答案 4 :(得分:1)
我也有办法...不是很好。
这看起来像@ 0xPwn的解决方案,但是他第二次没有反转向量。 您可能会理解此代码,所以我将不解释它。
#include <algorithm>
#include <vector>
template <typename T>
void pop_front(std::vector<T>& vec){
std::reverse(vec.begin(),vec.end()); // first becomes last, reverses the vector
vec.pop_back(); // pop last
std::reverse(vec.begin(),vec.end()); // reverses it again, so the elements are in the same order as before
}