带 set 的 std::inserter - 插入到 begin() 或 end()?
我有一些看起来像这样的代码:
std::set<int> s1, s2, out;
// ... s1 and s2 are populated ...
std::set_intersection(s1.begin(), s1.end(),
s2.begin(), s2.end(),
std::inserter(out, out.end()));
我读过,如果插入到集合中的值立即跟随作为“提示”给出的迭代器,则插入可以在摊销常数时间内完成。这在运行集合交集时显然是有益的,特别是因为写入 out
的所有内容都已按排序顺序排列。
我如何保证这种最佳性能?创建 std::inserter
时,out
为空,因此 out.begin() == out.end()
所以我不能看看我指定 out.begin()
还是 out.end()
作为提示有什么区别。但是,如果在 begin()
处插入每个元素时解释这一点,那么我似乎不会获得最佳的算法性能。这可以做得更好吗?
I have some code that looks like this:
std::set<int> s1, s2, out;
// ... s1 and s2 are populated ...
std::set_intersection(s1.begin(), s1.end(),
s2.begin(), s2.end(),
std::inserter(out, out.end()));
I've read inserts can be done in amortized constant time if the value being inserted to the set immediately follows the iterator given as a "hint". This would obviously be beneficial when running the set intersection, especially since everything being written to out
is already in sorted order.
How do I guarantee this optimal performance? When creating the std::inserter
, out
is empty so out.begin() == out.end()
so I can't see it makes any difference whether I specify out.begin()
or out.end()
as the hint. However, if this is interpreted at inserting every element at begin()
, it doesn't seem that I would get the optimum algorithmic performance. Can this be done better?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我选择 Alexander Gessler 的答案作为“正确”答案,因为它引导我找到了这个解决方案,我想无论如何我都会发布该解决方案。我编写了一个
last_inserter()
,它保证插入位置始终是最后一个元素的迭代器(如果为空则为 begin() ),因为set
需要一个指向实际插入位置之前的元素的迭代器,以获得最佳性能(因此不是 end() - 它将是实际插入位置之后的一个)。原始示例的用法如下:
这保证插入提示始终是最后一个元素的迭代器,希望在对具有排序范围的集合使用输出迭代器时提供最佳情况性能,如上所述。
下面是我的实现。我认为它是特定于 Visual C++ 2010 的 STL 实现的平台,因为它很大程度上基于现有的
insert_iterator
,而且我只能通过从std::_Outit
派生来使其工作。如果有人知道如何使其便携,请告诉我:I've chosen Alexander Gessler's answer as the 'correct' answer, because it led me to this solution, which I thought I would post anyway. I've written a
last_inserter()
, which guarantees that the insert position is always an iterator to the last element (or begin() if empty), becauseset
wants an iterator to the element preceding the actual insert position for best performance (so not end() - that would be one after the actual insert position).The usage as per the original example is like this:
This guarantees that the insert hint is always an iterator to the last element, hopefully providing best-case performance when using an output iterator to a set with a sorted range, as above.
Below is my implementation. I think it's platform specific to Visual C++ 2010's STL implementation, because it's based heavily on the existing
insert_iterator
, and I can only get it working by deriving fromstd::_Outit
. If anyone knows how to make this portable, let me know:您可以使用自定义函子代替
std::inserter
,并在每次插入新元素时重新调用out.end()
。或者,如果您的值按降序排序,则
out.begin()
也可以。You could use a custom functor instead of
std::inserter
and re-callout.end()
every time a new element is inserted.Alternatively, if your values are sorted descendingly,
out.begin()
will be fine.根据 http://gcc.gnu.org/onlinedocs /gcc-4.8.0/libstdc++/api/a01553_source.html
其中
iter
最初指向您传递给std::inserter
的迭代器。因此 iter 将始终指向您刚刚插入的值之后的一个,如果您按顺序插入,则应该具有最佳效率。According to http://gcc.gnu.org/onlinedocs/gcc-4.8.0/libstdc++/api/a01553_source.html
Where
iter
originally pointed to the iterator you passed tostd::inserter
. So iter will always point to one past the value you just inserted and if you're inserting in order, should be optimally efficient.