【问题标题】:C++ Find in a vector of <int, pair>C++ 在 <int, pair> 的向量中查找
【发布时间】:2020-12-17 14:44:45
【问题描述】:

所以以前我只有一个需要查找的键,所以我可以使用地图:

std::map <int, double> freqMap;

但现在我需要查找 2 个不同的键。我正在考虑使用带有 std::pair 的向量,即:

std::vector <int, std::pair<int, double>> freqMap;

最终我需要查找两个键以找到正确的值。有没有更好的方法来做到这一点,或者这是否足够有效(将有大约 3k 个条目)。此外,不确定如何使用第二个键(std::pair 中的第一个键)进行搜索。是否根据第一个密钥找到该对?基本上我可以通过以下方式访问第一个键:

freqMap[key1]

但不确定如何迭代并找到该对中的第二个键。

编辑:好的,添加用例进行说明:

我需要根据 2 个键、一个多路复用器选择和一个频率选择来查找一个 val。原始数据如下所示:

Mux, Freq, Val
0, 1000, 1.1
0, 2000, 2.7
0, 10e9, 1,7
1, 1000, 2.2
1, 2500, 0.8
6, 2000, 2.2

【问题讨论】:

  • 你为什么说两个,却用std::pair作为?当您说您需要查找两个键时,您的意思是您需要访问给定任何一个键的值,还是需要知道两个键才能找到该值?
  • 请举例说明您想做什么。我觉得描述有点混乱。
  • 是的,我需要两个键才能找到值。我正在考虑使用对 (int) 中的第一个元素作为第二个键,而 double 将是我想要返回的值。
  • 那为什么不把 Key 设为pair&lt;int, int&gt; 呢?即有一个vector&lt;pair&lt;pair&lt;int,int&gt;, double&gt;&gt;。在这种情况下,你也可以map&lt;pair&lt;int,int&gt;, double&gt;

标签: c++ vector find key-value std-pair


【解决方案1】:

“哪个更快”的笼统答案通常是“您必须对其进行基准测试”。

但除此之外,您还有很多选择。 std::map 在纸面上比其他数据结构更有效,但在实践中不一定。如果您确实处于对性能至关重要的情况(即避免过早优化),请尝试不同的方法,如下所示,并测量您获得的性能(内存方面和 cpu 方面)。


不要使用std::map,而是考虑将您的数据放入struct,给它适当的名称并将所有值存储在一个简单的std::vector 中。如果您很少修改数据,您可以通过 sorting 根据您通常用于查找条目的键来优化检索成本,但会增加插入成本。这将允许您执行binary search,这可以linear search 快得多。

但是,由于cache localitybranch prediction 的存在,线性搜索在std::vector 上的速度惊人地快。在处理地图、unordered_map 或(二进制搜索的)排序向量时,这两者都可能会丢失。因此,虽然 O(n) 听起来比 map 的 O(log n) 甚至 unordered_map 的 O(1) 更可怕,但在正确的条件下它仍然更快。 p>

特别是如果您发现您没有可用于对条目进行排序的可识别索引成员,您将不得不坚持在连续内存(即向量)中进行线性搜索投资进入双索引数据结构(实际上类似于两个映射或两个无序映射)。拥有两个索引通常会阻止您使用单个 map/unordered_map。

如果您可以更紧密地打包数据(即您需要int 还是std::uint8_t 来完成这项工作?,您是否需要double?等等)您将放大缓存局部性,并且仅用于3k 个条目,您很有可能使未排序的向量表现最佳。尽管对 std::size_t 的操作本身通常比对较小类型的操作要快,但在连续内存上进行迭代通常会抵消这种影响。


结论:尝试一个未排序的向量、一个排序的向量(+二分查找)、一个地图和一个 unordered_map。进行适当的基准测试(多次重复)并选择最快的一个。如果没有区别,请选择最容易理解的那个。


编辑:鉴于您的示例数据,听起来第一个键的域非常小。据我所知,“Mux”似乎仅限于少量彼此靠近的不同值,在这种情况下,您可以考虑使用 std::array 作为您的主要索引结构并具有合适的查找结构为你的第二个。例如:

std::array<std::vector<std::pair<std::uint64_t,double>>,10>
std::array<std::unordered_map<std::uint64_t,double>,10>

【讨论】:

  • 要考虑的另一件事是使用模式。数据多久修改一次,多久查询一次?换句话说,更重要的是:插入成本还是搜索成本?
  • @VladFeinstein 是的,我指出了这一点,但可能没有足够强调这一点。让我看看如何改进它。
  • @bitmask 感谢您的解释。你是对的,多路复用器的选择只会是 0-7,所以我想我会试试你对 std::array 地图的建议。仅供参考,插入所有元素是一次点击,搜索会发生数千次。
  • @SSB 在这种情况下,真正看看使用向量是否更快(排序或未排序)。这听起来违反直觉,我知道,但我一次又一次地看到它。 map 和 unordered_map 是为了方便,array 和 vector 是为了性能。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-14
  • 1970-01-01
  • 2019-02-20
  • 1970-01-01
相关资源
最近更新 更多