[英]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)
。 (同樣重要的是,Hash和Equals始終為相同的參數產生相同的值。我曾經認為不用說,但是我已經看到了幾個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]
范圍內,並且可以生成該范圍內的所有整數。 因此,考慮用簡單的數組(即圖像)替換哈希表。 圖像是將像素位置映射到值的最佳數據結構。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.