我怎样才能插入到一个集合和一个德克
How can I insert into a set and a deque
我有一个C++函数,它需要将一系列连续的整数插入到一个集合中,并在取消排队结束时以与迭代相同的顺序插入该集合的每个新元素。 下面是一个大约为 O(log(n( * n( 的解决方案,因为重复插入每个都是 O(log(n((。 我想得到一个 O(n( 解决方案。 我想使用采用提示迭代位置的 set::insert((,但如果我这样做,我不知道如何在恒定时间内确定该项目是否已经在集合中。
#include <deque>
#include <set>
void
insertUnique(const int beginOffset,
const int endOffset,
std::set<int> &sent,
std::deque<int> &recent)
{
for (int offset = beginOffset; offset < endOffset; ++offset) {
const bool inserted = sent.insert(offset).second;
if (inserted) {
recent.push_back(offset);
}
}
}
有没有办法将其重构为 O(n( 并完成相同的工作,同时保持函数的参数不变? 有没有办法使用迭代器提示插入并知道是否插入了该项?
如果sent
仅用于确定整数是否已排队,那么我建议使用std::unordered_set
,因为所有插入和搜索都有平均常量时间。
但是,除非你的套装会变得很大,否则它不太可能产生太大的影响。
事实上,如果记录的不同整数的数量小于 ~1000,那么你甚至可以使用向量获得更好的实际性能,特别是如果你保持它的排序 - 因为std::find()
使用二进制搜索,这是 O(logN( 时间,但没有指针取消引用并且具有良好的内存局部性。
编辑:
只是为了好玩,我尝试了几次,但问题是sent
是一个set<>
,没有比 O(logN( 更快的插入方法。
这个将集合复制到unordered_set(平均恒定时间操作(,但最终插入是logN :-(
void
insertUnique_average_constant(const int beginOffset,
const int endOffset,
std::set<int> &sent,
std::deque<int> &recent)
{
std::unordered_set<int> temp_sent(begin(sent), end(sent));
for (int offset = beginOffset; offset < endOffset; ++offset) {
const bool inserted = temp_sent.insert(offset).second;
if (inserted) {
recent.push_back(offset);
}
}
sent.insert(begin(temp_sent), end(temp_sent));
}
如果你能忍受的话,这个可能会有一些希望。它试图使用set_difference(O2n(来减少必须发送然后缓存的项目集的大小,因此理论上随着sent
集的扩展,它的效率会提高。
// a minimal iterator that simply serves the next int in sequence
struct next_index_iterator
{
using value_type = int;
next_index_iterator(int value)
: _value(value)
{}
bool operator==(const next_index_iterator& that) const {
return this->_value == that._value;
}
next_index_iterator& operator++() {
++_value;
return *this;
}
next_index_iterator operator++(int) {
return next_index_iterator(_value + 1);
}
const int& operator*() const {
return _value;
}
private:
int _value;
};
// necessary for set_difference to compile
namespace std {
template<>
struct iterator_traits<next_index_iterator>
{
using value_type = next_index_iterator::value_type;
};
}
void
insertUnique_sort_of_2N(const int beginOffset,
const int endOffset,
std::set<int> &sent,
std::deque<int> &recent)
{
std::vector<int> to_send;
to_send.reserve(endOffset - beginOffset);
// set_difference is O(2N)
std::set_difference(std::begin(sent), std::end(sent),
next_index_iterator(beginOffset),
next_index_iterator(endOffset),
std::back_inserter(to_send));
// at this point to_send contains only the offsets we have not sent
for (const auto offset : to_send) {
recent.push_back(offset);
}
// but we still have to insert these into `sent` at the end
sent.insert(std::begin(to_send), std::end(to_send));
}
相关文章:
- 大三实现在一个集合类
- (也许是NP-Hard)求一个集合的子集总数,使得每个子集在与其所有元素相乘时的值都大于X
- 维护多集中数字的排序列表和另一个集合中的累积总和
- std::set的替代品(可以将元素从一个集合移动到另一个集合)
- 如果您在c++中更新一个集合的成员,该集合会自动更改顺序吗
- 如何制作一个集合,其中元素使用局部变量进行排序
- 增强 MPL 将每个元素包装在一个集合中
- 我怎样才能插入到一个集合和一个德克
- C++在一个集合中存储多个数据类型
- 如何在C++中检查一个集合是否有某个范围内的元素
- 计算一个集合中不同于另一个集合的元素数
- 当返回一个集合指针时,客户端如何知道它是否需要销毁它?
- 从一个集合生成所有可能的有序子集
- 如何检验一个集合是否自反、对称、反对称和/或传递
- 如何将一个集合分成K个子集,使得子集中元素的和最小
- 将unique_ptr从一个集合移动到另一个集合
- 在c++中反转一个集合的内容
- 对于每个模板类型,都有一个集合类型的实参
- 生成一个集合的所有子集,使它们的集合等于整个集合
- 一个集合是否可能包含指向同一对象的两个共享指针?