明显的(天真的?)方法是:
std::set<int> s;
for (int i = 0; i < SIZE; ++i) {
s.insert(i);
}
这是合理的可读性,但从我的理解,不是最优的,因为它涉及重复搜索插入位置,并没有利用输入序列已经排序的事实。
使用一系列数字初始化std::set
是否有更优雅/高效(或事实上)的方法?
或者,更一般地说,如何有效地将有序的条目列表插入到集合中?
浏览文档,我刚刚注意到接受迭代器的构造函数来指示插入的位置:
iterator insert ( iterator position, const value_type& x );
这意味着这会更有效:
std::set<int> s;
std::set<int>::iterator it = s.begin();
for (int i = 0; i < SIZE; ++i) {
it = s.insert(it, i);
}
看起来合理,但我仍然愿意接受更多建议。
答案 0 :(得分:19)
用作提示的正确迭代器在C ++ 03和C ++ 11之间发生了变化。使用C ++ 03,您希望使用上一项的位置(正如您和大多数回复所示)。
在C ++ 11中,你希望在之后立即使用迭代器你要插入的那个。当您按顺序插入时,这会使事情变得更简单:您始终使用your_container.end()
:
std::set<int> s;
for (int i = 0; i < SIZE; ++i)
s.insert(s.end(), i);
当然,您可以使用算法(例如,std::iota
)或迭代器(例如,boost::counting_iterator
,如已提到的@pmr)来生成您的值,但就插入本身而言对于当前实现,您希望使用.end()
作为提示,而不是前一次插入返回的迭代器。
答案 1 :(得分:14)
最漂亮的是:
#include <set>
#include <boost/iterator/counting_iterator.hpp>
int main()
{
const int SIZE = 100;
std::set<int> s(boost::counting_iterator<int>(0),
boost::counting_iterator<int>(SIZE));
return 0;
}
如果您的目标是提高原始效率,使用提示插入版本可能会有所帮助:
const int SIZE = 100;
std::set<int> s;
auto hint = s.begin();
for(int i = 0; i < SIZE; ++i)
hint = s.insert(hint, i);
能够将hint
与计数器一起声明会很好并给我们一个干净的范围,但这需要struct
hackery,我觉得有点混淆。
std::set<int> s;
for(struct {int i; std::set<int>::iterator hint;}
st = {0, s.begin()};
st.i < SIZE; ++(st.i))
st.hint = s.insert(st.hint, st.i);
答案 2 :(得分:4)
#include <algorithm>
#include <set>
#include <iterator>
int main()
{
std::set<int> s;
int i = 0;
std::generate_n(std::inserter(s, s.begin()), 10, [&i](){ return i++; });
}
这是(我认为)相当于你的第二个版本,但恕我直言看起来好多了。
C ++ 03版本将是:
struct inc {
static int i;
explicit inc(int i_) { i = i_; }
int operator()() { return i++; }
};
int inc::i = 0;
int main()
{
std::set<int> s;
std::generate_n(std::inserter(s, s.end()), SIZE, inc(0));
}
答案 3 :(得分:3)
您可以使用insert()
版本的set<>
,您可以在其中提供位置作为提示插入元素的位置。
iterator insert ( iterator position, const value_type& x );
复杂性:此版本通常是对数的,但如果在位置指向的元素之后插入x
,则摊销常数。
答案 4 :(得分:1)
这可以用一行代码完成。 lambda捕获可以将变量i
初始化为0
,并且可变说明符允许i
在lambda函数中进行更新:
generate_n( inserter( s, s.begin() ), SIZE, [ i=0 ]() mutable { return i++; });