【问题标题】:How do I get the max element of a std::unordered_map?如何获得 std::unordered_map 的最大元素?
【发布时间】:2019-09-21 11:58:29
【问题描述】:

我知道如何通过使用std::max_element 来检索std::map 的最大元素,但由于容器类型之间的差异,我无法使用std::unordered_map 实现相同的效果。

如何在std::unordered_map 中找到最大值并返回对应的std::pair

显示了我当前使用std::map 执行此操作的方法(基于this answer)。我似乎不知道如何为std::unordered_map 做同样的事情。

template <typename KEY_T, typename VALUE_T>
std::pair<KEY_T, VALUE_T> findMaxValuePair(
    std::map<KEY_T, VALUE_T> const &x)
{
    return *std::max_element(x.begin(), x.end(),
                             [](const std::pair<KEY_T, VALUE_T> &p1,
                                const std::pair<KEY_T, VALUE_T> &p2)
                             {
                                 return p1.second < p2.second;
                             });
}

当我尝试在std::unorderd_map 上使用上述函数时(将std::map 替换为std::unordered_map,我收到Segmentation fault (core dumped)

【问题讨论】:

  • 当您在这里简单地将std::map 替换为std::unordered_map 时会发生什么?
  • @SamVarshavchik 出现Segmentation fault (core dumped)
  • @paddycakes -- 然后你需要发布一个minimal reproducible example。我们不知道您在何处、何时或如何调用此函数。
  • 这一定是由于其他一些与代码无关的问题;但不幸的是,无法弄清楚某些未显示的代码有什么问题;但只有显示的代码符合minimal reproducible example 的所有要求,如stackoverflow.com 的help center 中所述。
  • @paddycakes 此外,您的std::map 版本很可能隐藏了该错误。你应该很高兴unordered_map 发现了它。

标签: c++ c++17 unordered-map


【解决方案1】:

使代码为unordered_map工作

在这种情况下,我们实际上只需将类型从 map 更改为 unordered_map 即可。

之前:

template <class Key, class Value>
std::pair<Key, Value> findMaxValuePair(
    std::map<Key, Value> const &x)
{
    return *std::max_element(x.begin(), x.end(),
                             [](const std::pair<Key, Value> &p1,
                                const std::pair<Key, Value> &p2)
                             {
                                 return p1.second < p2.second;
                             });
}

之后:我们将类型更改为unordered_map

template <class Key, class Value>
std::pair<Key, Value> findMaxValuePair(
    std::unordered_map<Key, Value> const &x)
{
    return *std::max_element(x.begin(), x.end(),
                             [](const std::pair<Key, Value> &p1,
                                const std::pair<Key, Value> &p2)
                             {
                                 return p1.second < p2.second;
                             });
}

让代码对双方都有效

我们可以非常简单地编写一个适用于所有标准容器的函数!这适用于地图、矢量、列表以及几乎所有其他定义 begin()end()value_type 的东西!

template <class Container>
auto findMaxValuePair(Container const &x)
    -> typename Container::value_type
{
    using value_t = typename Container::value_type;
    const auto compare = [](value_t const &p1, value_t const &p2)
    {
        return p1.second < p2.second;
    };
    return *std::max_element(x.begin(), x.end(), compare);
}

segmentation fault 呢?

如果地图或容器为空,则此代码可能会出现分段错误,因为您正在访问您不拥有的内存;因为map::end() 指向的内存包含垃圾,然后您尝试从中构造类似字符串的东西,或者因为它被表示为空指针。

特别是对于地图,如果存在内存损坏,也可能导致分段错误,尽管这与您尝试迭代地图的方式无关。

【讨论】:

  • 我确信 OP 已经想到了这一点(您可以在问题的评论部分阅读)。
  • 段错误是与用于查找最大元素的算法无关的问题,但我更新了答案以解决可能的原因
  • 按照您的建议。由于地图为空而发生段错误。 if(x.size() ==0) return Container::value_type(); 支票解决了这个问题。
  • 好的!很高兴听到这个消息!
  • @paddy 在空或错误时返回标志值是个坏主意。
【解决方案2】:

有序映射,顾名思义,是有序的,但是是按键。在这里,您的目标是价值观。

在任何一种情况下,您都需要遍历整个地图才能找到最大值。有序映射可以有效地找到最大或最小键,但不能找到值。因此,采用全扫描方法将适用于无序或有序地图。

如果您需要有效地找到最大值,您可能会考虑将代码更改为使用有序集、逆序映射(值与键)或有序包(同一键的多值映射)

【讨论】:

  • 你说的“除了钥匙”是什么意思
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-20
  • 2018-11-27
  • 1970-01-01
  • 1970-01-01
  • 2015-04-05
  • 1970-01-01
相关资源
最近更新 更多