C++ STL容器,将顺序排序与恒定访问时间相结合?

C++ STL容器,将顺序排序与恒定访问时间相结合?,c++,stl,C++,Stl,我觉得这是我应该在Stackoverflow上找到的东西,但也许我在这里搜索了错误的术语 我有一个场景,其中有一个类 class Foo { int key; int b; ... } 我想把这个类的新元素推到一个列表上。事先不知道项目的数量 同时,我希望能够使用某个键快速检查(并检索)元素的存在性,例如key==5 因此,总结一下: 它应该有O(1)(或其附近)以供存在/检索/删除 它应该保留推送项目的顺序 对此,我想到了一个解决方案:“使用std::list存储项目,使用s

我觉得这是我应该在Stackoverflow上找到的东西,但也许我在这里搜索了错误的术语

我有一个场景,其中有一个类

class Foo
{
  int key;
  int b;
  ...
}
我想把这个类的新元素推到一个列表上。事先不知道项目的数量

同时,我希望能够使用某个键快速检查(并检索)元素的存在性,例如key==5

因此,总结一下:

  • 它应该有O(1)(或其附近)以供存在/检索/删除
  • 它应该保留推送项目的顺序
对此,我想到了一个解决方案:“使用std::list存储项目,使用std::unordered_映射检索项目,并进行一些簿记”。我当然可以自己实现它,但我想知道类似的东西是否已经以一种方便的形式存在于STL中


编辑:为了抢占建议,std::map不是一个解决方案,因为它是基于某个键进行排序的。也就是说,它不会保留我推送项目时的顺序。

STL没有那种容器,您可以使用std::unordered_映射和std::list编写自己的容器。将键映射到std::unordered_映射中的列表迭代器,并将键值对存储在std::list中

void add(const Key& key, const Value& value) 
{
    auto iterator = list.insert(list.end(), std::pair<Key, Value>(key, value));
    map[key] = iterator;
}

void remove(const Key& key)
{
    auto iterator = map[key];
    map.erase(key);
    list.erase(iterator);
}
void添加(常量键和键、常量值和值)
{
自动迭代器=list.insert(list.end(),std::pair(key,value));
map[key]=迭代器;
}
无效删除(常数键和键)
{
自动迭代器=映射[键];
地图。擦除(键);
删除(迭代器);
}
或者使用boost多索引容器
在STL,没有什么类似的东西,或者现代C++标准库(我假设是STL所指的),但是Boost .O.(1)是棘手的部分,STD::MAP是O(log)至少。一旦你有了它,在std::vector或链表中存储指向元素的指针将解决第二个约束。
std::unordered_map
是“几乎”O(1)。因此,将其与
std::list
结合使用是满足OP复杂性要求的合理方法。当然,使用Boost可能是一种更稳健的方法。当然,直到渐近复杂性在实践中占据主导地位之前,可能需要大量的n,因此度量性能将非常重要。这种“O”表示法可能很棘手。O(n)并不意味着它总是比O(1)慢,只是,对于n的某个值或更大的值,它会变慢。对于简单类型(例如具有基本数据类型的类),可能少于1000个(取决于许多因素,例如类型和CPU的大小),您可能会发现使用
std::find
std::vector
比其他更“聪明”的数据结构要快得多,这些数据结构承诺“更好”的O评级。这是因为缓存性能更好,动态内存分配更少。(例如,
std::list
动态分配每个节点。速度非常慢。)当然,唯一确定的方法是测量。是的,这就是我想的。事实上,我很惊讶它的代码如此简单。我认为列表中的迭代器不会因为删除而失效?(不同于在映射中,重新灰化使所有迭代器无效)是的,您是对的,在std::list.BTW中,只有指向已删除对象的迭代器无效,是否有任何特定的原因将密钥作为一对存储在列表中的值旁边?似乎人们也可以只在列表中存储元素本身,从而减少内存。如果你想迭代键,你应该存储对。我明白了,是的。在我的特殊情况下,键是元素本身的一部分,因此对它的检索会将键与它一起提供给您。