2d(3d)坐标的散列图(即双精度矢量)?

时间:2013-05-28 12:59:15

标签: c++ hash c++11 hashmap

我想知道对于坐标{(1}}是否有一般的全面解决方案(在2d或3d中,即双精度矢量)?

示例here演示了如何为hash map创建自定义哈希映射, 但是从pair<int,int>(可能代表一个二维坐标)到pair<double,double>的独特地图出现似乎并不容易。

我知道我可以通过提供比较器对象来使用有序地图,但对于我的应用程序,不需要对它们进行排序,并且哈希映射似乎更快。 然而,由于我是所有这些size_t内容的新手,我对如何继续进行感到很失望。

p / s / i使用c ++ 11。

4 个答案:

答案 0 :(得分:3)

为避免额外的依赖关系,您可以使用std::hash。以下是使用您发布的链接中的代码的示例,并已更新为使用std::pair<double,double>

#include <unordered_map>
#include <cassert>

using namespace std;

class TPoint3D{
public:
    TPoint3D(double x, double y, double z) : x(x), y(y), z(z){};

    double x, y, z;
};

struct hashFunc{
    size_t operator()(const TPoint3D &k) const{
    size_t h1 = std::hash<double>()(k.x);
    size_t h2 = std::hash<double>()(k.y);
    size_t h3 = std::hash<double>()(k.z);
    return (h1 ^ (h2 << 1)) ^ h3;
    }
};

struct equalsFunc{
  bool operator()( const TPoint3D& lhs, const TPoint3D& rhs ) const{
    return (lhs.x == rhs.x) && (lhs.y == rhs.y) && (lhs.z == rhs.z);
  }
};

typedef unordered_map<TPoint3D, int, hashFunc, equalsFunc> TPoint3DMap;

int main(){
  TPoint3DMap myMap;

  // test equalsFunc
  myMap[TPoint3D(10.0, 20.0, 30.0)] = 100;
  myMap[TPoint3D(10.0, 20.0, 30.0)] = 200;

  assert(myMap[TPoint3D(10.0, 20.0, 30.0)] == 200);

  // test if hashFunc handles well repeated values inside TPoint3D
  myMap[TPoint3D(10.0, 10.0, 10.0)] = 1;
  myMap[TPoint3D(10.0, 20.0, 10.0)] = 2;
  myMap[TPoint3D(10.0, 10.0, 20.0)] = 3;
  myMap[TPoint3D(20.0, 10.0, 10.0)] = 4;

  assert(myMap[TPoint3D(10.0, 10.0, 10.0)] == 1);
  assert(myMap[TPoint3D(10.0, 20.0, 10.0)] == 2);
  assert(myMap[TPoint3D(10.0, 10.0, 20.0)] == 3);
  assert(myMap[TPoint3D(20.0, 10.0, 10.0)] == 4);

  return 0;
}

正如我之前所说,如果您希望使用其他结构,则必须同时调整pairHash类和pairEquals结构operator()以适当地散列并比较新密钥。

干杯

编辑:

  • 修改代码以使用自定义TPPoint3D类和统一仿函数类定义(均使用struct)。
  • 添加了简单的测试来验证哈希和等于仿函数。

答案 1 :(得分:3)

我无法评论Andre的答案,因为我还没有足够的声誉,但是任何尝试使用^(XOR)创建哈希函数的人都应该注意到XOR是关联的。换句话说(h1 ^ (h2 << 1)) ^ h3 。这意味着

h1 ^ ((h2 << 1) ^ h3)

这是Andre答案的返回值,与:

相同
a ^ b == b ^ a

由于XOR((h3 ^ (h2 << 1)) ^ h1 )的交换性质,它本身就相当于:

a

所有这一切意味着我所引用的哈希方法,对于不同的bc(a,b,c),将返回(c,b,a)的相同哈希值就像(h1 ^ (h2 << 1)) ^ (h3 << 2) 一样。换句话说,x和z坐标是顺序无关/不敏感的。

根据您使用此哈希方法的方式,这可能不是问题。但是,如果您正在散列的点与网格对齐,则会收到过多的散列冲突。

我会用下面的答案替换Andre答案中的return语句中的表达式。这应该是依赖于顺序/敏感的。

{{1}}

答案 2 :(得分:1)

使用Boost中的hash_combine怎么样?

http://www.boost.org/doc/libs/1_53_0/doc/html/hash/combine.html

答案 3 :(得分:1)

在3D情况下,std::unordered_map<std::tuple<double, double, double>, your_value_type>应该可以正常使用,假设您正在进行精确查找std::tuple<...>根据聚合类型的相等和散列函数为您定义相等和散列函数。

2D情况当然是相同的,但使用std::tuple<double, double>

编辑:对于错误信息感到抱歉。实际上没有为std::tuple定义的默认哈希。要使用此方法,您必须定义hash_tuple模板化仿函数类,然后在std::unordered_map中使用它。其他答案显示了如何做到这一点。