问题 为什么要使用无序容器? (C ++)


我已经尝试过搜索但没找到任何东西。

我正在学习STL容器,并了解顺序容器和关联容器的优缺点,但是我不确定为什么有人会更喜欢无关容器而不是关联容器,因为它肯定不会影响元素的插入,查找和删除。

它纯粹是一个性能的东西,即它需要更多的处理来插入/删除一个关联容器,因为它必须经过排序? 我不太了解系统方面的事情,但在我的脑海里,我觉得无序的容器需要比自动组织的更加“保养”。

如果有人能够解决一些问题,我将非常感激。


11031
2018-01-25 20:17


起源

显然,自动组织的那个需要更多的维护:它需要在它改变时重新组织。另一个没有。 - R. Martinho Fernandes
阅读书籍或尝试自己编写代码。随着经验的理解将来临。 - Sergey P. aka azure
你的术语令我困惑。你将“无序容器”与“关联容器”进行对比,但这两件事并不相互排斥。 std::map 和 std::unordered_map 是 都 关联数组。而 std::set 和 std::unordered_set 不是。 - Benjamin Lindley
“关联容器”表示“按值查找”,与“序列容器”形成对比,“序列容器”是“按插入位置查找”。 - Kerrek SB
好吧,我错了。我猜“关联容器”在C ++中意味着不同的东西。这包括 std::set 和变种。但它也包括无序变体,因此您的术语仍然令人困惑。 - Benjamin Lindley


答案:


纯粹抽象地考虑这样一个事实,即元素的排序是一个额外的“功能”,你必须付出代价,所以如果你不需要它(比如在查找字典中),那么你不应该付钱为了它。

从技术上讲,这意味着可以通过使用哈希表来实现无序容器,其具有预期的查找和插入复杂度O(1),而不是有序容器的O(log n)。

然而,在切线相关的说明中,有一个巨大的 实际的 使用字符串作为键时的优点:有序容器必须在树行走的每个地方执行完整的字符串比较,而散列容器只执行单个散列操作(甚至可以“优化”以仅从非常采样固定数量的字符长串),在实践中经常变得更快。

如果订购不是必需的,那么最好的办法是尝试  容器类型(其界面几乎相同)并比较其中的性能 你的 使用情况。


9
2018-01-25 20:27



你关于字符串比较的陈述对我来说似乎不直观。我期待 std::less<std::string> 是一个 急于 一旦找到第一个不匹配的字符就会返回的比较。反之, std::hash<std::string> 可能会计算整个字符串的哈希值。所以,如果您将长字符串作为键,但字符串在前几个字符中都有所不同(我知道这是一个人为的例子) map 可能比一个更好 unordered_map。此外,+ 1建议实际尝试它。 - Praetorian
在通常情况下,链接容器的成本 显着 超过了比较/散列计算本身的成本。看到 Bjarne关于C ++ 11风格的演讲 大约45分钟,就这种影响的程度进行了令人震惊的讨论。 - Andres Jaan Tack
@Praetorian字符串比较可能会比哈希更多次。 - Seth Carnegie
@Praetorian再想一想。哈希计算一次,其成本基本上等于将相同的字符串与相等的字符串进行一次比较。如果key完全在地图中,则必须在最终匹配元素中至少对字符串进行一次比较。因此,对于几乎所有实际应用,哈希 是 更快。 - hyde
@aspiring_programmer不,哈希确实是O(1),无论哈希大小。在任何给定时刻散列的每个项目平均重新进行一次,因此每个项目的插入成本平均保持在O(1),它不会增长,百万项目具有99.9999%的插入成本1和0.0001需要重新计算成本为百万的概率为百分之二,平均为2,即。恒定时间。 Hash基本上用作表索引,表访问当然也是O(1)。 - hyde


不确定为什么有人会更喜欢无序容器而非关联容器

这些功能并不是唯一的。容器可以是关联的,如果是,则也可以是无序的。

如果你熟悉的话 哈希映射,这就是无序容器利用的技术。 标准库使用术语“无序”而不是“散列”,以便在需要的时候不强加特定的技术只是特定的性能承诺。  (见评论)


2
2018-01-25 20:24



原因 unordered 被选中而不是 hash 是因为许多实现已经有了使用该单词的非标准版本 hash。 - Jesse Good
@JesseGood,真的是一种耻辱,看到如何 std:: 部分浪费。 - chris


我们使用无序容器当对象的排序没有必要时你最关心对象查找的性能,因为无序容器在任何地方都有最快的搜索/插入是O(1)而不是有序容器(关联容器取O(log n))和Sequence容器取O(n))。


0
2017-11-30 10:31