C++ 0x问题:将时间插入到std :: set中

Ala*_*ing 11 c++ complexity-theory stl insert set

根据这个页面,如果我使用,我可以实现恒定时间插入

iterator std::set::insert ( iterator position, const value_type& x );
Run Code Online (Sandbox Code Playgroud)

position我提供的迭代器直接"在"正确(有序)插入点之前.

现在我关心的情况是,如果我知道我插入的值最后(因为它是最大的),例如:

set<int> foo = {1, 2, 3};
foo.insert(4); // this is an inefficient insert
Run Code Online (Sandbox Code Playgroud)

根据上述标准,我应该将最后一个元素传递foo.end()-1insert foo.end().我的理解是否正确?如果我通过foo.end()会怎么样?它会是O(log n)插入还是插入O(1).所以,选项是:

// Option A
foo.insert(foo.end()-1, 4);

// Option B
foo.insert(foo.end(), 4);

// Safer version of Option A
if(foo.empty())
    foo.insert(4);
else
    foo.insert(foo.end()-1, 4);
Run Code Online (Sandbox Code Playgroud)

我问,因为我正在编写一个在容器上模板化的函数.我想在传入任何容器的末尾插入一个元素(我知道是最大的).使用上面的"选项A"对容器有不同的行为,如vector:

foo.insert(foo.end()-1, 4);
// result is {1, 2, 3, 4} if foo is an std::set
// result is {1, 2, 4, 3} if foo is an std::vector
Run Code Online (Sandbox Code Playgroud)

正如@Bo_Persson所暗示的,这里的问题是C++ 03说"一般是对数,但如果在p之后插入t,则摊销常数." 而C++ 0x表示"一般为对数,但如果在p之前插入t,则摊销常数."

PS:我在Ubuntu 11.04上使用GCC 4.5并启用了C++ 0x支持.

编辑:我运行经验测试,启用和禁用C++ 0x支持,并将结果发布到答案中.基本上,结论是提供end()插入提示同样好(并且显然更安全).然而,这显然只是一个经验观察.如上所述,标准在这方面仍然令人困惑.

ant*_*kos 4

运行测试而不阅读库规范是作弊吗?

对于g++-4.4 -O2整数,0 <= i < 5000000我的标准插入运行时间是

real    0m14.952s
user    0m14.665s
sys 0m0.268s
Run Code Online (Sandbox Code Playgroud)

我使用end()提示插入的运行时间是

real    0m4.373s
user    0m4.148s
sys 0m0.224s
Run Code Online (Sandbox Code Playgroud)

据我所知,插入 at 的end() - 1速度最快,但使用起来比较麻烦,因为它是end() - 1非法操作(您必须使用operator--()),并且如果集合碰巧为空,它就会崩溃。

#include <set>

typedef std::set<int> Set;

void insert_standard(Set& xs, int x)
{
    xs.insert(x);
}

void insert_hint_end(Set& xs, int x)
{
    xs.insert(xs.end(), x);
}

int main()
{
    const int cnt = 5000000;
    Set xs;
    for (int i = 0; i < cnt; i++) {
        // insert_hint_end(xs, i);
        insert_standard(xs, i);
    }
}
Run Code Online (Sandbox Code Playgroud)