【问题标题】:c++ cannot find element is unordered_set with the same hashc ++找不到元素是具有相同哈希的unordered_set
【发布时间】:2020-02-21 10:15:37
【问题描述】:

我有用于无序向量集的自定义散列函数:

struct VectorHash {
int operator()(const vector<int> &V) const {
    int hsh=V[0] + V[1];
    return  hash<int>()(hsh);
}};

对于两个这样的向量,我有相同的哈希等于 3:

vector<int> v1{2,1};
vector<int> v2{1,2};

但是当我尝试在 unordered_set 中插入第一个向量 v1,然后通过哈希检查我是否在我的 unordered_set 中具有与 v2 相同的向量时,我得到了错误:

std::unordered_set<std::vector<int>, VectorHash> mySet;
mySet.insert(v1); 

if(mySet.find(v2) == mySet.end())
    cout << "didn't find" << endl;

Output:  "didn't find"

我假设如果 unordered_set 中的两个元素具有相同的哈希值,那么如果我的 unordered_set 中有 v1,当我尝试查找 v2 时,find 方法应该返回 true。但事实并非如此。

谁能解释一下我的推理有什么问题?

【问题讨论】:

    标签: c++ unordered-set


    【解决方案1】:

    哈希不是万能的,您在这里看到的是碰撞。

    这里std::vector&lt;int&gt;的hash值相同,但是计算hash后,std::unordered_map实际上会使用operator==检查元素是否相等,在这种情况下会失败,然后失败找到元素。

    碰撞在 HashMaps 中是很正常的事情,如果不提供自定义 operator==,您将无法在此处进行任何操作。

    【讨论】:

    • std::unordered_set 接受一个比较器作为第三个参数,您可以像他为 VectorHash 所做的那样创建一个比较器并获得他正在寻找的结果,而无需使用 unordered_map
    【解决方案2】:

    我假设如果 unordered_set 中的两个元素具有相同的哈希值,那么如果我的 unordered_set 中有 v1,当我尝试查找 v2 时,find 方法应该返回 true。

    这个假设是不正确的,相同的哈希值并不意味着对象是相等的。

    unordered_map 使用相等谓词来确定键相等(默认为std::equal_to)。

    【讨论】:

      【解决方案3】:

      如果您碰巧想要唯一标识符但不自动比较值,则可以使用 (unordered_)map&lt;int, vector&lt;int&gt;&gt; 并使用该 VectorHash 函数生成 int 键:

      unordered_map<int, vector<int>> map;
      
      int key=V[0] + V[1]
      map[key] = V;
      

      【讨论】:

        【解决方案4】:

        您还需要为unordered_set 提供一个比较器,如果您希望这两个元素匹配,您可以执行以下操作:

        struct VectorComparator {
          bool operator()(const std::vector<int> & obj1, const std::vector<int> & obj2) const
          {
            if ((obj1[0] + obj1[1]) == (obj2[0] + obj2[1]))
              return true;
            return false;
          }
        };
        

        并像这样创建您的unordered_set

        std::unordered_set&lt;std::vector&lt;int&gt;, VectorHash, VectorComparator&gt; mySet;

        那么你应该得到你期望的结果

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-04-14
          • 2019-06-13
          • 2020-03-25
          • 2018-11-13
          • 2011-10-04
          • 1970-01-01
          • 2011-11-11
          • 1970-01-01
          相关资源
          最近更新 更多