唯一的成员资格 FIFO 容器
Unique membership FIFO container
我需要一个先进先出的队列,该队列包含ID并捕获仅当ID尚未在队列中时才应添加。
我能想到的最好的方法是:
typedef unsigned ID;
struct UniqueFifo
{
private:
std::set<ID> ids; // keep track of what is already in
std::queue<ID> fifo; // keep in fifo order
public:
void push(ID x) {
// only add to queue if not already in it
if(ids.find(x) == ids.end()) {
fifo.push(x);
ids.insert(x);
}
}
ID pop() {
// pop from queue
ID x = fifo.front();
fifo.pop();
// and also remove from map
ids.erase(x);
return x;
}
};
有没有更优雅的方法可以使用C++ STL 容器来做到这一点?
使用像这样的第二种数据结构,针对插入和搜索进行了优化,是最具可扩展性的解决方案;但是,如果队列永远不会变得特别大,那么在队列本身中进行线性搜索可能会更有效(当然也更简单)。您需要deque
本身,而不是queue
适配器才能访问内容。
如果它足够大,可以证明可搜索的"索引"是合理的,那么考虑使用unordered_set
(如果可用)或其他一些基于哈希的集合(如果不是);如果你只需要唯一性而不是任何特定的排序,这可能会更快。
代码需要将 ID 插入到集合和队列中。方便的是,您可以将其与唯一性检查相结合,这样只需要一次搜索:
if (ids.insert(x).second) {
fifo.push(x);
}
您还可以考虑在队列中存储集合迭代器而不是值,以提高擦除效率。
你的解决方案还不错,但你需要使用std::set<ID>
,而不是std::map
(映射用于将键映射到值,而你只关心这里的值)。如果c++11
可用,还可以考虑使用 std::unordered_set
。
一点也不差。我可以看到其他方法可以做到这一点,主要是使用一个容器(因为我看到的唯一"问题"是你使用 2 个容器,因此必须一直断言它们彼此一致),但它们并不更优雅,可能成本更高。
恕我直言,使用std::unordered_set
而不是std::set
来控制此设计(至少是此界面),直到您可以对性能进行基准测试。之后,您可能没有问题,或者std::set
中的额外查找对您来说太高了。在这种情况下,您可以尝试保留std::queue<std::pair<ID, std::unordered_set<ID>::const_iterator>>
以简化擦除(如果删除不在 there元素上,则std::set
和std::unordered_set
迭代器不会因添加或删除而失效)。
但除非你需要更好的表现,否则不要这样做。您的代码简单易读。
- 在提升multi_index容器中,是否定义了"default index"?
- 用于访问容器<T>数据成员的正确 API
- Eigen如何在容器循环中干净地附加矩阵
- 模板专用化(按容器):value_type
- 关联容器的下界复杂性:成员函数与非成员函数
- 更多constexpr容器是否需要mark_immutable_if_consexpr
- 在STL容器中使用模板类
- 当有分配器意识的容器被复制/移动时,反弹分配器是否被复制/移走
- 即使我读取了所有内容,在FIFO上打开的QSocketNotifier也会一直启动
- 检查函数返回类型是否与STL容器类型值相同
- STL算法函数在多个一维容器上的使用
- 如何将带有自定义对象的容器从C++传递到QML
- 在没有未定义行为的情况下实现类似std::vector的容器
- 将 BASE 派生类存储在同一容器中
- 为什么 STL 容器适配器堆栈中的 top 返回常量引用?
- 在C++中迭代 2D 容器的最干净方法
- 将线程中的数据存储到全局容器的最佳方法?
- 如果我真的真的想从 STL 容器继承,并且我继承构造函数并删除新运算符,会发生什么?
- 唯一的成员资格 FIFO 容器
- STL容器,用于单个生产商-单个消费者FIFO