C++哈希表 - 如何解决自定义数据类型作为键的unordered_map冲突?
C++ Hash Table - How is collision for unordered_map with custom data type as keys resolved?
我定义了一个名为Point
的类,它将用作unordered_map
中的键。因此,我在类中提供了一个operator==
函数,并且还提供了std::hash
template specialization
。根据我的研究,这是我发现必要的两件事。相关代码如下所示:
class Point
{
int x_cord = {0};
int y_cord = {0};
public:
Point()
{
}
Point(int x, int y):x_cord{x}, y_cord{y}
{
}
int x() const
{
return x_cord;
}
int y() const
{
return y_cord;
}
bool operator==(const Point& pt) const
{
return (x_cord == pt.x() && y_cord == pt.y());
}
};
namespace std
{
template<>
class hash<Point>
{
public:
size_t operator()(const Point& pt) const
{
return (std::hash<int>{}(pt.x()) ^ std::hash<int>{}(pt.y()));
}
};
}
// Inside some function
std::unordered_map<Point, bool> visited;
该程序在我测试的情况下编译并给出了正确的结果。但是,我不相信在使用用户定义的类作为键时这是否足够。在这种情况下,unordered_map
如何知道如何解决冲突?我是否需要添加任何内容来解决冲突?
这是一个可怕的哈希函数。但它是合法的,所以你的实现会起作用。
哈希和等于的规则(实际上是唯一的规则(是:
- 如果
a == b
,则std::hash<value_type>(a) == std::hash<value_type>(b)
。
(同样重要的是,哈希和等于始终为相同的参数生成相同的值。我曾经认为这是不言而喻的,但我见过几个 SO 问题,unordered_map产生意想不到的结果,正是因为这些函数中的一个或两个都依赖于某个外部值。
这将通过始终返回 42 的哈希函数来满足,在这种情况下,地图在填满时会变得非常慢。但除了速度问题之外,代码还可以工作。
std::unordered_map
使用链式哈希,而不是开放寻址哈希。具有相同哈希值的所有条目都放置在同一个存储桶中,这是一个链表。因此,低质量的哈希不能很好地在存储桶之间分配条目。
很明显,您的哈希给出{x, y}
和{y, x}
相同的哈希值。更严重的是,小矩形中的任何点集合都将共享相同数量的不同哈希值,因为哈希值的高阶位都将相同。
知道Point
旨在将坐标存储在图像中,这里最好的哈希函数是:
pt.x() + pt.y() * width
其中width
是图像的宽度。
考虑到x
是[0, width-1]
范围内的值,上面的哈希函数为任何有效的值pt
生成一个唯一的数字。不可能发生碰撞。
请注意,如果将图像存储为单个内存块,则此哈希值对应于点pt
的线性索引。也就是说,给定y
也在有限的范围内([0, height-1]
(,所有生成的哈希值都在[0, width* height-1]
范围内,并且可以生成该范围内的所有整数。因此,请考虑将哈希表替换为简单的数组(即图像(。图像是将像素位置映射到值的最佳数据结构。
- 写入位置0x0000000C时发生访问冲突
- GL_SHADERSTORAGE_BUFFER位置是否与其他着色器位置冲突
- 使用cmake从源代码构建MySQL连接器/C++失败(与以前的声明冲突)
- 引发异常:读取访问冲突**dynamicArray**为0x1118235.发生
- C++LinkedList问题.数据类型之间存在冲突?没有匹配的构造函数
- 链表中写入访问冲突的未知原因
- C++中的openCV Mat访问冲突
- 如何使 std::sort 在 std::swap 和我的命名空间的模板化交换之间没有名称冲突?
- C++尝试深度复制唯一指针时出现内存访问冲突
- 错误:使用通用引用的声明冲突
- 如何解决GTest和LibTorch联动冲突
- 两个运营商的一些奇怪的冲突<<
- 如何在多个线程中创建 QSql数据库连接时防止名称冲突
- C++ 中动态二维数组的访问冲突
- 从嵌套循环中的 std::list 中删除将返回访问冲突
- C++17 十六进制浮点文字单精度后缀冲突?
- 结构字段名称与 GDB 中的 STL 数组冲突
- 写入访问冲突异常
- C++ |匿名命名空间与命名空间 std 冲突
- 这个SSDO演示的GLSL版本要求是自我冲突的吗