在C ++中,我有一个std :: set,我想插入一系列连续的整数。我怎样才能有效地做到这一点,希望在O(n)时间内,其中n是范围的长度?
我在想我会使用std :: insert的inputIterator版本,但是我不清楚如何构建输入迭代器。
std::set<int> mySet;
// Insert [34 - 75):
mySet.insert(inputIteratorTo34, inputIteratorTo75);
如何创建输入迭代器,这将是范围大小的O(n)?
答案 0 :(得分:4)
将已经排序的元素插入集合的有效方法是提示库以确定下一个元素的位置。为此你想使用带有迭代器的insert
版本:
std::set<int>::iterator it = mySet.end();
for (int x : input) {
it = mySet.insert(it, x);
}
另一方面,您可能想要考虑其他容器。尽可能使用std::vector
。如果与查找相比插入量较小,或者所有插入都是预先发生的,那么您可以构建一个向量,对其进行排序并使用lower_bound
进行查找。在这种情况下,由于输入已经排序,您可以跳过排序。
如果在整个地方发生插入(或移除),您可能需要考虑使用std::unordered_set<int>
插入(每个元素)和查找费用平均O(1)
。
对于跟踪集合中小数字的特殊情况,所有这些都很小(34到75是小数字),您还可以考虑使用位集,甚至是bool
的简单数组,您可以在其中设置插入时true
的元素。要么O(n)
插入(所有元素)和O(1)
查找(每次查找),要好于集合。
答案 1 :(得分:2)
Boost方式可能是:
std::set<int> numbers(
boost::counting_iterator<int>(0),
boost::counting_iterator<int>(10));
其他答案很棒 LINK ,特别是@Mani的回答
答案 2 :(得分:1)
std :: set是一种二叉搜索树,这意味着插入成本平均为O(lgn),
c ++ 98:如果插入N个元素,通常是Nlog(大小+ N),但是是线性的 如果元素已经按照相同的顺序排序,则大小为+ N. 容器使用的订购标准。
c ++ 11:如果插入N个元素,则为Nlog(大小+ N)。实施可能 如果范围已经排序,则进行优化。
我认为C ++ 98工具将跟踪当前插入节点并检查下一个要插入的值是否大于当前值,在这种情况下,不需要再次从root开始。
在c ++ 11中,这是一个可选的优化,因此你可以实现一个skiplist结构,并在你的工具中使用这个范围插入的feture,或者你可以根据你的场景优化programm
答案 3 :(得分:1)
根据aksham提供的提示,我看到答案是:
#include <boost/iterator/counting_iterator.hpp>
std::set<int> mySet;
// Insert [34 - 75):
mySet.insert(boost::counting_iterator<int>(34),
boost::counting_iterator<int>(75));
答案 4 :(得分:0)
目前尚不清楚为什么要特意插入使用迭代器来指定范围。
但是,我相信您可以使用简单的for循环插入所需的O(n)复杂度。
从std :: set的cppreference页面引用,复杂性为:
如果插入N个元素,一般是Nlog(大小+ N),但如果元素已根据容器使用的相同排序标准排序,则大小为线性+ N.
所以,使用for循环:
std::set<int> mySet;
for(int i = 34; i < 75; ++i)
mySet.insert(i);