快速实现pop_front到std :: vector的方法

时间:2012-02-25 15:29:50

标签: c++ data-structures vector pop

我正在使用一些类和几个使用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());
}

这两种解决方案的速度有多快?还有其他解决方案吗?

5 个答案:

答案 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

}