【问题标题】:Efficient way to hash a 2D point散列二维点的有效方法
【发布时间】:2014-11-30 03:48:27
【问题描述】:

好的,所以任务是这样的,我将得到 (x, y) 点的坐标,其中 (x, y) 的范围从 -10^6 到 10^6(含)。我必须检查一个特定的点,例如(x, y) 元组是否给了我。简而言之,我如何回答是否设置了特定点(2D)的查询。到目前为止,我能想到的最好的方法是维护std::map<std::pair<int,int>, bool>,每当给出一个点时,我将其标记为 1。虽然这必须以对数时间运行并且是回答查询的相当优化的方式,但我想知道是否有更好的方法这样做。

另外,如果有人能说出如果我使用上述数据结构作为哈希,我会很高兴。我的意思是std::map 的复杂度将是 O(log N) in元素的大小与键的结构无关?

【问题讨论】:

  • 很久没有回答我的问题了。请不要马上举报这个:(
  • std:map 通常使用平衡二叉树而不是哈希表来实现。如果您不关心地图中元素的顺序(您似乎不关心),您可以使用std:unordered_map
  • 我在使用 std::unordered_map 时遇到一堆错误,请在这里帮助我!!
  • 我在使用 std::unordered_map 时遇到一堆错误,请在这里帮助我!!您需要比这更具体才能获得任何帮助.
  • 好的,我的std::unordered_map的结构是unordered_map , int> MAP; ,我正在使用 MAP[make_pair(x, y)] = value; ,我在使用 C++11 编译时遇到这些错误,/usr/include/c++/4.8/bits/functional_hash.h:58:12: error: declaration of 'struct std::hash<:pair int> >' 结构哈希;

标签: c++ optimization hash map


【解决方案1】:

与其将每个点映射到一个布尔值,为什么不将给定的所有点存储在一个集合中呢?然后,您可以简单地搜索该集合以查看它是否包含您要查找的点。它与您正在执行的操作基本相同,而无需额外查找相关的布尔值。例如:

set<pair<int, int>> points;

然后,您可以像这样检查集合是否包含某个点:

pair<int, int> examplePoint = make_pair(0, 0);
set<pair<int, int>>::iterator it = points.find(examplePoint);

if (it == points.end()) {
    // examplePoint not found
} else {
    // examplePoint found
}

如前所述,std::set 通常实现为平衡二叉搜索树,因此每次查找都需要 O(logn) 时间。

如果您想改用哈希表,您可以使用std::unordered_set 而不是std::set 来做同样的事情。假设您使用了一个好的散列函数,这将使您的查找速度提高到 O(1) 时间。但是,为了做到这一点,您必须为pair&lt;int, int&gt; 定义散列函数。这是取自this答案的示例:

namespace std {
template <> struct hash<std::pair<int, int>> {
    inline size_t operator()(const std::pair<int, int> &v) const {
        std::hash<int> int_hasher;
        return int_hasher(v.first) ^ int_hasher(v.second);
    }
};

}

编辑:没关系,我看到你已经开始工作了!

【讨论】:

  • 是的,这很酷,我本可以使用 std::set,我怎么从来没想到 :P。是的,我得到了它的工作,无论如何谢谢你的答案。
【解决方案2】:

要使用哈希映射,您需要使用std::unordered_map 而不是std::map。使用它的限制是您的值类型需要为它定义一个散列函数,如in this answer 所述。要么,要么只使用boost::hash

std::unordered_map&lt;std::pair&lt;int, int&gt;, boost::hash&lt;std::pair&lt;int, int&gt; &gt; map_of_pairs;

另一个想到的方法是将 32 位 int 值存储在一个 64 位整数中,如下所示:

uint64_t i64;
uint32_t a32, b32;
i64 = ((uint64_t)a32 << 32) | b32;

this answer 中所述。 x 和 y 分量可以存储在整数的高字节和低字节中,然后您可以使用std::unordered_map&lt;uint64_t, bool&gt;。虽然我很想知道这是否比以前的方法更有效,或者它是否会产生不同的代码。

【讨论】:

  • Thanx,@Martin Liversage 提到使用这个,但我遇到了奇怪的错误,这是由你提到的值类型的限制所解释的,我正在努力
  • 好吧,我尝试了你提供链接的方法,通过定义一个哈希函数,它起作用了,执行时间减少到原来的 75%(大约)!
  • 很高兴听到这个消息,我是哈希映射的忠实粉丝,如果哈希函数繁重且映射很小,它们的效率可能会降低,但通常 O(1) 很难争论与。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-04-16
  • 2018-01-27
  • 2020-05-06
  • 2019-10-27
  • 2015-08-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多