两个成员中任意一个成员的哈希

Hashing by either one of two members

本文关键字:成员 哈希 任意一 两个      更新时间:2023-10-16

虽然这个问题是关于c++的,但它是一个通用的哈希问题,可能也适用于其他语言。

我有一个类,它由它拥有的两个成员中的一个来标识(让我们称它们为device&name)。

class Foo {
    static const int NO_DEVICE = 0;
    bool isDeviceSet() {
        return device != NO_DEVICE;
    }
private:
    int device;
    std::string name;
};

我想识别一个优先级高于deviceFoo实例(当它被设置时)
也就是说,当设置device时,我希望根据device进行散列(仅-这样,具有相同device和不同name的两个Foo将被视为相同的对象散列)
当未设置device时,我希望根据name进行散列。

我的问题:

其中任何一个成员的散列是否足够安全?

例如,任何一种方法的散列都是这样的:

namespace std {
    size_t hash<Foo>::operator()(Foo const& f) const {
        if (f.isDeviceSet()) {
            return std::hash<int>()(f.deviceId);
        }
        return std::hash<std::string>()(f.name);
     }
}

这方面的问题是,人们可能会争辩说(根据每个哈希函数的实现),两个不同的Foo,一个具有device集,一个没有device集,具有相同哈希代码的概率是未知的(尽管可能性很小)。

  • 考虑一个int散列函数,它转换为字符串并调用字符串的散列——这将导致Foo{2, "bar"}Foo{0, "2"}具有相同的散列代码

另一方面,我不确定在散列中组合isDeviceSet()是否真的会给出更好的结果(对于一般情况——显然它解决了上面项目符号中的例子):

namespace std {
    size_t hash<Foo>::operator()(Foo const& f) const {
        if (f.isDeviceSet()) {
            std::pair<bool, int> p(f.isDeviceSet(), f.device);
            boost::hash< std::pair<bool, int> > hasher;
            return hasher(p);
        }
        std::pair<bool, std::string> p(f.isDeviceIdSet(), f.name);
        boost::hash< std::pair<bool, std::string> > hasher;
        return hasher(p);
     }
}

欢迎任何见解/其他杂烩想法。

哈希总是与相等一起进行。

您需要定义一个相等操作,该操作与您认为相等的元素匹配,与您认为不相等的元素不匹配。

然后定义一个散列函数,该函数必须具有等式认为等于同一散列代码的所有元素。对于被认为不平等的元素,根本没有任何要求。

任何涉及哈希的算法都必须在不相等对象的相等哈希代码中生存,而不会出现问题;如果可能的对象比可能的散列码多,则永远不可能保证不同对象的散列码不同。即使您的哈希函数只返回0,任何使用它的算法都应该正常工作,除非可能效率较低。

当你考虑制作哈希函数有多复杂时:它应该只让具有相同哈希代码的现有对象集变小。它不一定是完美的,除非你有一个真正性能关键的哈希表。但是散列函数本身在某种程度上也是性能关键的。