将参数传递给 unordered_map(或集合)哈希结构
Posted
技术标签:
【中文标题】将参数传递给 unordered_map(或集合)哈希结构【英文标题】:Pass a parameter to an unordered_map (or set) hash struct 【发布时间】:2020-08-24 16:35:10 【问题描述】:我有以下结构:
array<int, 2> map_size;
struct Node
int id;
array<int, 2> pos;
vector<Node*> nbs;
bool in_open;
bool in_closed;
;
每个节点都有一个在 map_size(全局变量)范围内的位置 (pos)。
我正在使用以下无序地图
struct PosHash
public:
size_t operator()(array<int, 2> const& pos) const
return pos[1] + pos[0]*map_size[1];
;
struct PosCompare
bool operator()(const array<int, 2>& pos1, const array<int, 2>& pos2) const
if (pos1[0] == pos2[0] and pos1[1] == pos2[1])
return true;
else
return false;
;
unordered_map<array<int, 2>, Node*, PosHash, PosCompare> nodes;
map_size 是散列函数中使用的全局变量,可以让我得到一个完美的散列。 但是,我想将 map_size 作为参数传递给 PosHash,这样可以避免使用全局变量。我该怎么做?
PD:map_size 值在执行时间确定
【问题讨论】:
为PosHash
拥有一个map_size
数据成员怎么样。让它的构造函数初始化它。然后将此对象传递给unordered_map
的构造函数(在适当的位置)
map_size
是您的地图的关键。
pos[]
是Node
中的变量,而这又是unordered_map
中的映射值。散列函数PosHash
应该接收键值并产生Node
s,即pos[]
。为什么哈希函数需要映射值来产生映射值?
@User10482 我认为就是这样。但是不知道怎么在unordered_map这一行传参数(map_size是在执行时决定的)
@Lingo 这是针对 A* 的。在 A* 中,我将开始和目标位置作为数组这是一个完整的程序,展示了如何构造一个存储特定值的PosHash
对象。请注意,您不需要自定义比较 - std::array
s 无论如何都会以相同的方式进行比较。
#include <iostream>
#include <array>
#include <unordered_map>
using Pos = std::array<int, 2>;
struct PosHash
PosHash(int m) : m_m
size_t operator()(const Pos& pos) const
return pos[1] + pos[0] * m_;
int m_;
;
int main()
static constexpr size_t initial_bucket_count = 5;
// for illustrative purposes, will just map to ints
std::unordered_map<Pos, int, PosHash> minitial_bucket_count, PosHash4;
m[Pos2, 3] = 23;
m[Pos1, 1] = 11;
m[Pos3, 1] = 11;
m[Pos3, 2] = 32;
for (const auto& x : m)
std::cout << x.first[0] << ',' << x.first[1] << '=' << x.second << '\n';
更一般地说,这是一个“弱”哈希函数。它可能是“完美”地产生足够分散的散列值以避免散列值空间中的冲突,但这并不意味着如果你将该空间折叠到较少数量的桶中,你就不会发生冲突。
【讨论】:
谢谢!这正是我所需要的。我不知道如何将地图大小传递给 unordered_map。无论如何,我知道这个哈希函数是完美的,因为具有相同位置的节点总是相同的节点。这个哈希函数返回地图的一维数组中的位置。 现在我知道问题出在桶的数量上,如果桶的数量有限,最好使用像 djb2 这样的标准字符串哈希函数 @BMarin:哦,很好-我想知道是否应该尝试进一步解释。为多部分键组合散列的合理通用方法是hash_combine
- 你基本上会说 size_t seed = 0; hash_combine(seed, pos[0]); hash_combine(seed, pos[1]);
然后使用 seed
作为你的散列值。【参考方案2】:
您可以将map_size
作为PosHash
结构中的数据成员。
struct PosHash
public:
size_t operator()(array<int, 2> const& pos) const
return pos[1] + pos[0]*map_size[1];
// Contructor that initializes the data member
PosHash(std::intializer_list<int> map_dim) : map_size(map_dim)
// Other stuff
;
std::array<int, 2> map_size; // data member of the struct
;
然后,您可以使用所需的 map_size
数组构造一个 PosHash
对象。将此对象传递给您的unordered_map
PosHash myPosHash(1, 2);
std::unordered_map<array<int, 2>, Node*, PosHash, PosCompare> nodes(\\intial args\\, myPosHash);
查看std::unordered_map
here 的不同可用构造函数。您需要在 hasher 参数之前显式指定所有参数。这些将取决于您的需求。
我能想到的最简单的是
nodes(0, myPosHash); //initial #buckets, hasher object
【讨论】:
我该如何初始化 unordered_map? @BMarin 添加。您可以按照自己的方式获得PosHash
的构造函数和其他详细信息。希望这会有所帮助。
Tony Delroy 的回答有初始化地图的正确方法,略有不同,还是谢谢!以上是关于将参数传递给 unordered_map(或集合)哈希结构的主要内容,如果未能解决你的问题,请参考以下文章
将 Laravel 集合中的 id 参数传递给 Vue 组件
如何将无限参数和一个或两个参数传递给 JavaScript 函数? [复制]