C++ 无序的_映射-哈希函数无效

C++ 无序的_映射-哈希函数无效,c++,hash,unordered-map,C++,Hash,Unordered Map,为什么在下面的例子中,哈希函数(返回常量0)似乎没有任何效果 因为散列函数返回常量,所以我希望输出的所有值都是3。然而,它似乎将std::vector值唯一地映射到一个唯一的值,而不管我的哈希函数是常量 #include <iostream> #include <map> #include <unordered_map> #include <vector> // Hash returning always zero. class TVector

为什么在下面的例子中,哈希函数(返回常量0)似乎没有任何效果

因为散列函数返回常量,所以我希望输出的所有值都是3。然而,它似乎将
std::vector
值唯一地映射到一个唯一的值,而不管我的哈希函数是常量

#include <iostream>
#include <map>
#include <unordered_map>
#include <vector>


// Hash returning always zero.
class TVectorHash {
public:
    std::size_t operator()(const std::vector<int> &p) const {
    return 0;
    }
};

int main ()
{
    std::unordered_map<std::vector<int> ,int, TVectorHash> table;

    std::vector<int> value1({0,1});
    std::vector<int> value2({1,0});
    std::vector<int> value3({1,1});

    table[value1]=1;
    table[value2]=2;
    table[value3]=3;

    std::cout << "\n1=" << table[value1];
    std::cout << "\n2=" << table[value2];
    std::cout << "\n3=" << table[value3];

    return 0;
}
预期产出:

1=1
2=2
3=3
1=3
2=3
3=3

关于散列,我遗漏了什么?

一个健全的散列表实现不应该丢失信息,即使存在散列冲突。有几种技术可以解决冲突(通常在运行时性能和数据完整性之间进行权衡)。 显然,
std::unordered_map
实现了它


请参阅:

您误解了哈希函数的用法:它不用于比较元素。在内部,map将元素组织到bucket中,hash函数用于确定元素所在的bucket。使用另一个模板参数对元素进行比较,查看
unordered_map
模板的完整声明:

template<
    class Key,
    class T,
    class Hash = std::hash<Key>,
    class KeyEqual = std::equal_to<Key>,
    class Allocator = std::allocator< std::pair<const Key, T> >
> class unordered_map;
模板<
类密钥,
T类,
类Hash=std::Hash,
类KeyEqual=std::等于,
类分配器=std::分配器
>类无序图;
哈希器之后的下一个模板参数是键比较器。要获得预期的行为,您必须执行以下操作:

class TVectorEquals {
public:
    bool operator()(const std::vector<int>& lhs, const std::vector<int>& rhs) const {
        return true;
    }
};

std::unordered_map<std::vector<int> ,int, TVectorHash, TVectorEquals> table;
std::unordered_map<std::vector<int> ,int, TVectorHash, TComparer> table;
class-tvector等于{
公众:
布尔运算符()(常数std::vector&lhs,常数std::vector&rhs)常数{
返回true;
}
};
std::无序的_映射表;

现在,您的映射将只有一个元素,所有结果都将是
3

添加谓词键比较器类

class TComparer {
public:
    bool operator()(const std::vector<int> &a, const std::vector<int> &b) const {
        return true; // this means that all keys are considered equal
    }
};
类比较程序{
公众:
布尔运算符()(常数std::vector&a,常数std::vector&b)常数{
return true;//这意味着所有键都被认为是相等的
}
};
像这样使用它:

class TVectorEquals {
public:
    bool operator()(const std::vector<int>& lhs, const std::vector<int>& rhs) const {
        return true;
    }
};

std::unordered_map<std::vector<int> ,int, TVectorHash, TVectorEquals> table;
std::unordered_map<std::vector<int> ,int, TVectorHash, TComparer> table;
std::无序映射表;

然后,代码的其余部分将按预期工作。

当散列意外地对不同的数据变为相同时,您的数据会消失吗?我不希望它消失。但是如果散列函数将不同的键映射到同一位置,我希望数据会被覆盖其中
table
std::unordered_map
?事实上,我想这样做,但显然没有简单的方法将整数序列映射到唯一索引中。因此,我试图了解无序映射(以及映射)是如何做到这一点的。@rkioji谁说无序映射(以及映射)是这样做的?那么,这是否意味着拥有一个常量散列函数实际上会将散列数据结构折叠成一个简单的链表(或者用于解决冲突的任何其他数据结构)?有没有办法在C++中禁用这个?@ RKOOJI相同的哈希!同样的元素。根据定义,所有哈希映射都是这样工作的。如果希望数据结构只存储具有相同哈希的每个元素中的一个,请使用不同的相等比较器使映射确信具有相同哈希的元素是相同的。@rkioji更像一个简单的动态数组。尽管如此,查找复杂性仍然是O(N),因为它使用
操作符==
或相等比较器按顺序搜索数组。