插入前面的矢量

时间:2010-11-19 15:44:33

标签: c++ performance vector

iterator insert ( iterator position, const T& x );

std::Vector类的插入运算符的函数声明。

此函数的返回类型是指向插入元素的迭代器。我的问题是,鉴于这种返回类型,最有效的方法是什么(这是我运行的大型程序的一部分,速度至关重要,所以我正在寻找大多数计算效率的方式)在开头插入。是以下吗?

//Code 1
vector<int> intvector;
vector<int>::iterator it;
it = myvector.begin();
for(int i = 1; i <= 100000; i++){
    it = intvector.insert(it,i);
}

或者,

//Code 2
vector<int> intvector;
for(int i = 1; i <= 100000; i++){
    intvector.insert(intvector.begin(),i);
}

基本上,在代码2中,是参数

intvector.begin() 
与在代码1中使用返回的迭代器相比,计算评估的“成本”还是应该同样便宜/昂贵?

9 个答案:

答案 0 :(得分:108)

如果您的程序的一个关键需求是在容器的开头插入元素:那么您应该使用std::deque而不是std::vectorstd::vector只擅长在最后插入元素。

STL diagram for choosing containers

C ++ 11中引入了其他容器。我应该开始使用这些新容器找到更新的图表并将其插入此处。

答案 1 :(得分:41)

获得插入点的效率至少无关紧要 - 每次插入时不断改变现有数据的效率会相形见绌。

使用std :: deque,就是它的设计目的。

答案 2 :(得分:25)

旧帖子,但它出现在同事的办公桌上,作为Google查询的第一个搜索结果。

使用值得考虑的双端队列有一种替代方法:

std::vector<T> foo;
for (int i = 0; i < 100000; ++i)
  foo.push_back(T());
std::reverse( foo.begin(), foo.end() );

你仍然使用一种比deque更具工程性的矢量来提高性能。此外,交换(反向使用)是非常有效的。另一方面,复杂性虽然仍然是线性的,但却增加了50%。

与往常一样,在决定做什么之前进行衡量。

答案 3 :(得分:12)

如果你正在寻找一种计算效率高的插入方式,那么你可能想要使用deque而不是vector。

答案 4 :(得分:12)

最有可能deque是其他人建议的合适解决方案。但只是为了完整性,假设你需要只进行一次前插,在程序的其他地方你不需要在前面做其他操作,否则vector提供你需要的接口。如果所有这些都是真的,您可以使用非常高效的push_back然后reverse向量添加项目以使所有内容按顺序排列。这将具有线性复杂性,而不是像在前面插入时那样的多项式。

答案 5 :(得分:2)

使用矢量时,通常会知道它将具有的实际元素数。在这种情况下,保留所需数量的元素(在您显示的情况下为100000)并使用[]运算符填充它们是最快的方法。如果您确实需要在前面有效插入,可以使用dequelist,具体取决于您的算法。

您也可以考虑反转算法的逻辑并在最后插入,这通常对矢量更快。

答案 6 :(得分:2)

如果您真的想在开头插入数据,我认为您应该更改容器的类型。这就是为什么vector没有push_front()成员函数的原因。

答案 7 :(得分:1)

直觉上,我同意@Happy Green Kid Naps并进行了一项小测试,表明对于小尺寸(原始数据类型的1 << 10个元素)没有关系。但是,对于较大的容器大小(1 << 20),std::deque的性能似乎比反转std::vector的性能更高。因此,在决定之前先进行基准测试。另一个因素可能是容器的元素类型。

  • 测试1:将push_front(a)1 << 10或(b)1 << 20 uint64_t放入 std :: deque
  • 测试2:将(a)1 << 10或(b)1 << 20 uint64_t推入 std :: vector ,后跟 std :: reverse li>

结果:

  • 测试1-deque(a)19 µs
  • 测试2-矢量(a)19 µs
  • 测试1-双端(b)6339 µs
  • 测试2-矢量(b)10588 µs

答案 8 :(得分:0)

您可以支持-

  1. 在前面插入。
  2. 最后插入。
  3. 在任何位置更改值(不会出现在双端队列中)
  4. 访问任何索引处的值(不会出现在双端队列中)

以上所有操作的时间复杂度均为 O(1)

注意:你只需要知道 max_size 的上限,它可以左右移动。

class Vector{
public:
    int front,end;
    int arr[100100];   // you should set this in according to 2*max_size
    Vector(int initialize){
        arr[100100/2] = initialize; // initializing value 
        front = end = 100100/2;     
        front--;end++;
    }
    void push_back(int val){
        arr[end] = val;
        end++;
    }
    void push_front(int val){
        if(front<0){return;} // you should set initial size accordingly
        arr[front] = val;
        front--;
    }
    int value(int idx){
        return arr[front+idx];
    }
    // similarity create function to change on any index
};

int main(){
    Vector v(2);
    for(int i=1;i<100;i++){
        // O(1)
        v.push_front(i);
    }

    for(int i=0;i<20;i++){
        // to access the value in O(1)
        cout<<v.value(i)<<" ";
    }
    return;
}