【发布时间】:2015-05-01 07:59:54
【问题描述】:
这让我印象深刻,因为我应该可以在 Stackoverflow 上找到,但也许我在这里搜索错误的术语。
我有一个类的场景
class Foo
{
int key;
int b;
...
}
我想将该类的新元素推送到列表中。项目数量事先未知。
同时,我希望能够快速检查(并检索)具有特定键的元素的存在,例如键==5。
所以,总结一下:
- 存在/检索/删除应该有 O(1)(或大约)时间
- 应该保持推送项的顺序
对此的一个解决方案让我印象深刻,“使用 std::list 存储项目,并使用 std::unordered_map 检索它们,并进行一些簿记”。我当然可以自己实现它,但想知道这样的东西是否已经以方便的形式存在于 STL 中。
编辑:为了抢占建议,std::map 不是解决方案,因为它基于某个键进行排序。也就是说,它不会保留我推送项目的顺序。
【问题讨论】:
-
在 STL 或现代 C++ 标准库中没有类似的东西(我认为这就是您所说的 STL),但 Boost 有 multi-index containers。
-
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动态分配每个节点。非常慢。) -
当然,唯一确定的方法就是测量。