来自std :: map或std :: unordered_map的哪个容器适合我的情况

时间:2015-12-30 19:22:53

标签: c++ unordered-map stdmap

我不知道红黑树是如何使用字符串键的。我已经在youtube上用数字看过它了,它让我很困惑。但是我非常清楚unoredred_map是如何工作的(哈希映射的内部)。 std :: map对我来说保持深奥,但我读过并测试过,如果我们在std :: map中没有很多变化,它可以击败哈希映射。

我的情况很简单,我有<std::string,bool>的std :: map。键包含XML元素的路径(键的示例:&#34; Instrument_Roots / Instrument_Root / Rating_Type&#34;),我在SAX解析器中使用布尔值来了解我们是否到达了特定元素。

我制作这张地图&#34;只有一次&#34 ;;然后我所做的就是使用std :: find搜索特定的&#34;键&#34; (&#34; path&#34;)的存在是为了将其布尔值设置为true,或搜索具有&#34; true&#34;的第一个元素。作为关联值并使用其对应的键#34;最后我将所有布尔值设置为false以保证只有一个键#34;有一个真实的&#34;布尔值。

2 个答案:

答案 0 :(得分:3)

您不应该了解红黑树的工作原理,以了解如何使用std::map。它只是一个关联数组,其中键是有序的(字典顺序,在字符串键的情况下,至少与默认比较函数)。这意味着您不仅可以在std::map中查找密钥,还可以进行依赖于订单的查询。例如,您可以在地图中找到不大于您所拥有的密钥的最大密钥。你可以找到下一个更大的钥匙。或者(在字符串的情况下)你可以找到所有以相同前缀开头的键。

如果您遍历std::map中的所有键值对,您将按键顺序查看它们。这有时非常有用。

额外的功能是有代价的。 std::map通常比std::unordered_map慢(但并非总是如此;对于大字符串键,计算哈希函数的开销可能会很明显),并且底层数据结构有一定的开销,因此它们可能会占用更多空间。通常的建议是使用std::map,如果您发现密钥被命令为必要或甚至有用的事实。

但是,如果您已经对基准测试并得出结论,对于您的应用程序,std::map也更快,那么请继续使用它:)

有一个映射类型为bool的地图偶尔会有用,但前提是你需要区分对应值为false的键和地图中不存在的键。 。实际上,std::map<T, bool>(或std::unordered_map<T, bool>)为每个可能的密钥提供了三元选择。

如果您不需要区分两个false个案例,并且您不经常更改某个键的值,那么使用std::set(或{{}可能会更好1}}),这是完全相同的数据结构,但没有每个元素中std::unordered_set的开销。 (尽管bool中只有一位是有用的,但对齐考虑可能最终会为每个条目使用8个额外字节。)除了存储空间之外,不会有太多(如果有的话)性能差异。 / p>

如果您确实需要三元案例,那么建议您将值设为bool而不是enumbooltrue在您的使用环境中意味着什么?我猜他们并不是指“真实”和“虚假”。相反,它们意味着“是属性路径”和“是元素路径”。通过使用false,可以使这种区别更加清晰(因此不易发生事故)。这不会涉及任何额外的资源,因为enum PathType {ATTRIBUTE_PATH, ELEMENT_PATH};在任何情况下都占用了8个字节的存储空间(因为对齐)。

顺便说一句,不能保证底层数据结构恰好是一个红黑树,尽管没有某种自平衡树就很难实现性能保证。我不知道这样的实现,但是例如可以使用k-ary树(对于一些小k)来利用SIMD向量比较操作。当然,需要针对适当的密钥类型进行自定义。

如果你想了解红黑树,你可能会比罗伯特塞奇威克的算法标准教科书更糟糕。在本书的网站上,您可以在chapter on balanced trees中找到简要说明的解释。

答案 1 :(得分:1)

我建议你使用std :: unordered_set,因为你真的不需要存储这个布尔标志,你也不需要保持这些xml标签的排序顺序所以std :: unordered_set似乎对我来说是合乎逻辑且最有效的选择。