7 位整数的哈希函数

Hash Function for a 7 digits int

我是散列 table 和函数的新手,所以如果有任何错误,我提前道歉。

我正在尝试在 C++ 中创建一个散列 table,用于包含大约 10 万个条目的列表,这些条目由一个 7 位数字组成。 问题是,我在尝试找出要使用的哈希函数时遇到了困难。

当使用 %100000 时,我得到了大约 65k 个唯一键,而有大约 90k 个唯一条目。这意味着大约 1/3 的数据会发生冲突。

这个哈希函数好用吗?或者在这种情况下是否有更好的功能可以使用以减少碰撞? 我的 table 尺寸应该是多少?

再次感谢!

编辑- 条目是 1 到 2 百万之间的数字。 是否可以使用数字本身作为密钥?或者散列 table 的键应该始终从 0 开始吗​​?

标准库在内部使用散列 table 提供了两种类型:std::unordered_mapstd::unordered_set

由于您的密钥类型是整数类型,您可以通过 std::unordered_map<YourIdType, YourDataType 非常方便地获得散列 table。您可以通过 theMap[someId] 轻松访问数据,但请注意,如果未找到密钥,则会创建一个新对象!如果这不是你想要的,你宁愿使用 theMap.find(someId),其中 returns 一个迭代器。

不过,缺点是您会存储 id 两次(在内部作为 std::pair<YourIdType, YourDataType>)。您可以使用 std::unordered_set 来避免这种情况。但是,为了能够这样做,您需要针对您的类型专门化 std::hashstd::equal_to

namespace std // you are not allowed to add to – with exception of specialisations
{
template<>
struct hash<YourDataType>
{
    size_t operator()(YourDataType const& object) const
    {
        return hash<YourIdType>()(object.id);
    }
};

// analogously equal_to with appropriate comparisons, possibly by
// comparing the object's addresses

或者,您可以提供自定义哈希类型(使用 C++20,甚至可以将 lambda 打包到 decltype 中)作为第二个模板参数设置,然后只为您的代码实现 operator==对象类型,或者如果您需要它与运算符进行不同的比较,则提供自定义相等比较器类型,例如:

// C++20 required:
using YourMapType = std::set
<
    YourDataType,
    decltype
    (
        [](YourDataType const& object)
        { return std::hash<YourIdType>()(object.id); }
    ),
    decltype
    (
        [](YourDataType const& o1, YourDataType const& o2)
        { return &o1 == &o2; } // TODO: comparisons as you need! 
    )
>;
// alternatively create custom types with appropriate operator() implementations

这里的缺点是——除了专业化的额外复杂性——你不能只通过 id 查找对象,而是你需要一个数据类型的完整对象。

那么哪个更appropriate/suitable?这取决于您的具体要求...