地图的大小比矢量好

At what size is map better than vector?

本文关键字:地图      更新时间:2023-10-16

我有一个对象集合,每个对象都有一个标识符(字符串)。现在我想知道我应该把它们存储为向量还是映射,所以要么是std::vector<cObject>,要么是std::map<std::string,cObject>。每个名称只能使用一次,所以我需要检查向量/映射是否存在给定名称。使用映射时,我会使用对数缩放的find(),而对于向量,我会迭代并测试oObject.name == newname,直到找到名称或到达末尾,这是线性缩放的。映射的缺点是名称存储两次,一次存储在对象内部,一次作为关键字。

虽然对于大型矢量/地图,地图总是会获胜,但我想知道在哪一点上是这样的,因为如果我只有多达10个对象要存储,那么地图似乎太夸张了。

这就引出了我的问题:与普通向量相比,映射在哪一点上(在性能方面)变得有利?如果预期的对象数量大约是10、100、1000甚至更大,我是否应该考虑使用地图?我承认这个问题相当模糊,但我希望无论如何都能得到一些建议,以了解何时使用哪个容器。

很难预测映射比矢量更有利的大小。但有几点你可以考虑:

  1. 映射基本上实现为二叉树,而向量实现为数组。因此,当有10到12个元素时,在数组中迭代比较容易,因为这将是一个线性搜索
  2. 映射比矢量快的点取决于处理器上的实现,以及你试图在其中存储的数据。我的最佳猜测是,5-20个元素的映射会更快。(但这只是一个猜测,我建议你为自己创建一个基准
  3. "默认情况下,当你需要一个容器时,使用向量"-Bjarne Stroustrup

您还可以发现这个C++容器备忘单非常有用

这取决于矢量和映射的实现方式,以及代码对它们执行的操作(例如,将元素添加到中间或末尾、删除元素、重复添加和删除等)。您需要测试和评测您的代码。即使是它们,答案也将取决于主机系统(例如缓存、流水线等)。

顺便说一句,如果对向量进行排序,则查找元素也会按对数缩放(例如,使用二进制搜索)。因此,你的比较基础(矢量线性,映射对数)是有缺陷的。

使用映射时,我会使用对数缩放的find(),而对于向量,我会迭代并测试oObject.name==newname,直到找到名称或到达末尾,这是线性缩放的。

不完全正确,您可以对向量中的对象进行排序,并使用对数复杂度的std::binary_search

映射的缺点是名称存储两次,一次存储在对象内部,一次作为关键字。

您可以将std::set与自定义比较器一起使用,这样您就不必单独存储密钥。

总的来说,Knuth说"过早的优化是万恶之源"。让你的程序可读,使用更容易的方法(我想是std::mapstd::unordered_map),如果你对这个容器有性能问题,以后再优化它。将这个容器封装在某个类中可能会很有帮助,所以以后你可以透明地替换其余代码的实现。