将整数对散列为数组索引?

时间:2018-03-20 09:40:02

标签: c++ dictionary vector hash

我有一组连续的,基于0的整数,表示网格中的顶点索引。

每个顶点至少连接2个其他顶点,以形成网格的边缘。

边缘由顶点对表示。因此,例如,(0,2)可能是顶点0和2之间的一条边。

目前,为了快速查找网格中的边,我将Edge类存储在std :: unordered_map中,并生成哈希,如下所示:

//sorted so (0, 2) and (2, 0) will return same hash
__int64 GetEdgeHash (int vertex1, int vertex2)
{
     return (__int64)min(vertex1, vertex2) * INT_MAX + max(vertex1, vertex2);    
}

但是,unordered_map在创建和查找期间有足够的开销,它在我的代码中的其他地方有明显的性能影响。我想知道是否有一种方法来散列整数对,使得每对对应于某个索引,其大小为< = numVertices * 2的数组(因为网格中的边数永远不会超过该值)。如果可能的话,我可以使用普通的std :: vector来存储我的边缘,处理它们会快得多。

显然目前不可能,因为我的哈希函数将返回0到4611686016279904256之间的任何值。

一种天真的方法,如:

int GetEdgeHash (int vertex1, int vertex2)
{
     return vertex1 + vertex;    
}

将满足数组大小限制,但显然会导致许多冲突。

还有另一种方法可以实现同一目标吗?

1 个答案:

答案 0 :(得分:0)

一个非常简单的解决方案可以基于您的初始方法,但不使用INT_MAX,而是使用现有顶点的数量:

uint64_t numberOfVertices;

uint64_t index(uint32_t vertex1, uint32_t vertex2)
{
    return vertex1 * numberOfVertices + vertex2;
}

此算法无冲突,但需要numberOfVertices的平方向量大小;但是,只有在你有一个固定(或至少,最大)的顶点数时才适用。

如果顶点的数量可能超过最大值,则可以e。 G。每次超过时复制最大值,但是,这需要重新 - " hash"矢量中的所有节点,i。即这是一项昂贵的操作,应该尽可能少地发生(重复最大可能已经足够罕见......)。