【问题标题】:C++ unordered_map where key is also unordered_mapC++ unordered_map 其中键也是 unordered_map
【发布时间】:2017-04-08 21:33:16
【问题描述】:

我正在尝试使用 unordered_map 和另一个 unordered_map 作为键(自定义哈希函数)。我还添加了一个自定义的 equal 函数,尽管它可能不需要。

代码没有按照我的预期执行,但我无法判断正在发生的事情。出于某种原因,执行 find() 时没有调用 equal 函数,这是我所期望的。

unsigned long hashing_func(const unordered_map<char,int>& m) {
    string str;
    for (auto& e : m)
        str += e.first;
    return hash<string>()(str);
}
bool equal_func(const unordered_map<char,int>& m1, const unordered_map<char,int>& m2) {
    return m1 == m2;
}

int main() {

    unordered_map<
        unordered_map<char,int>, 
        string,
        function<unsigned long(const unordered_map<char,int>&)>,
        function<bool(const unordered_map<char,int>&, const unordered_map<char,int>&)>
        > mapResults(10, hashing_func, equal_func);

    unordered_map<char,int> t1 = getMap(str1);
    unordered_map<char,int> t2 = getMap(str2);

    cout<<(t1 == t2)<<endl; // returns TRUE
    mapResults[t1] = "asd";
    cout<<(mapResults.find(t2) != mapResults.end()); // returns FALSE

    return 0;
}

【问题讨论】:

  • 看看你的哈希函数为两张地图返回了什么

标签: c++ dictionary hash stl unordered-map


【解决方案1】:

首先,等式运算符肯定是必需的,所以你应该保留它。

让我们看看你的无序映射的哈希函数:

string str;
for (auto& e : m)
    str += e.first;
return hash<string>()(str);

由于它是一个无序映射,根据定义,迭代器可以以任何顺序遍历无序映射的键。但是,由于哈希函数必须为同一个键产生相同的哈希值,这个哈希函数在这方面显然会失败。

此外,除了键本身之外,我还希望哈希函数还包括无序映射键的值。我想您可能希望这样做——因为两个无序映射被认为是相同的键,只要它们的键相同,而忽略它们的值。从问题中不清楚您的期望是什么,但您可能需要考虑一下。

【讨论】:

  • 是的,这就是问题所在,哈希函数没有为相同的键返回相同的值。它以某种方式逃脱了我的脑海。
【解决方案2】:

使用== 比较两个std::unordered_map 对象会比较映射是否包含相同的键。它无法判断它们是否以相同的顺序包含它们(毕竟这是一个 unordered 映射)。但是,您的 hashing_func 取决于地图中项目的顺序:hash&lt;string&gt;()("ab") 通常与 hash&lt;string&gt;()("ba") 不同。

【讨论】:

    【解决方案3】:

    一个好的起点是 hashing_func 为每个映射返回的内容,或者更容易的是 hashing_func 中的字符串构造生成的内容。

    这种类型的更明显正确的散列函数可能是:

    unsigned long hashing_func(const unordered_map<char,int>& m) {
        unsigned long res = 0;
        for (auto& e : m)
            res ^ hash<char>()(e.first) ^ hash<int>()(e.second);
        return res;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-24
      • 2021-01-22
      • 2014-12-14
      相关资源
      最近更新 更多