unordered_set
及其成员函数,如何定义?#include <unordered_set>
...
class A{
...
private:
std::unordered_set< std::pair<int, int> > u_edge_;
};
编译器错误:
错误:调用'std::unordered_set > ::unordered_set()'时没有匹配的函数
unordered_set
及其成员函数,如何定义?#include <unordered_set>
...
class A{
...
private:
std::unordered_set< std::pair<int, int> > u_edge_;
};
编译器错误:
错误:调用'std::unordered_set > ::unordered_set()'时没有匹配的函数
计算一对数据的哈希值没有标准方法。请在您的文件中添加以下定义:
struct pair_hash {
inline std::size_t operator()(const std::pair<int,int> & v) const {
return v.first*31+v.second;
}
};
std::unordered_set< std::pair<int, int>, pair_hash> u_edge_;
pair<T1,T2>
定义了相等性。对于不提供测试相等性方法的自定义类,您可能需要提供一个单独的函数来测试两个实例是否相等。boost::hash
来对std::pair
进行哈希处理(这样做后,你的代码也可以在g++下编译)。#include <unordered_set>
#include <boost/functional/hash.hpp>
class A
{
private:
std::unordered_set<
std::pair<int, int>,
boost::hash< std::pair<int, int> >
> u_edge_;
};
std::unordered_set
使用std::hash
模板计算其条目的哈希值,而对于键值对,没有std::hash
特化。因此,您需要执行两个操作:
std::pair<int, int>
)特化std::hash
。这里是一个简单的示例:
#include <unordered_set>
namespace std {
template <> struct hash<std::pair<int, int>> {
inline size_t operator()(const std::pair<int, int> &v) const {
std::hash<int> int_hasher;
return int_hasher(v.first) ^ int_hasher(v.second);
}
};
}
int main()
{
std::unordered_set< std::pair<int, int> > edge;
}
如其他答案中大多数已经提到的,在这个问题上,你需要为std::pair<int, int>
提供一个哈希函数。然而,自从C++11以来,你也可以使用lambda表达式代替定义一个哈希函数。以下代码以Sergey提供的解决方案为基础:
auto hash = [](const std::pair<int, int>& p){ return p.first * 31 + p.second; };
std::unordered_set<std::pair<int, int>, decltype(hash)> u_edge_(8, hash);
我想重复一下Sergey的声明:这个解决方案仅适用于一对整数。 这个答案提供了一个更普遍的解决方案的想法。
好的,这里有一个简单的解决方案,可以保证不会发生碰撞。只需将您的问题转化为现有的解决方案,即将您的int
对转换为string
,如下所示:
auto stringify = [](const pair<int, int>& p, string sep = "-")-> string{
return to_string(p.first) + sep + to_string(p.second);
}
unordered_set<string> myset;
myset.insert(stringify(make_pair(1, 2)));
myset.insert(stringify(make_pair(3, 4)));
myset.insert(stringify(make_pair(5, 6)));
尽情享受吧!
您需要为 std::hash<>
提供一个专门用于处理 std::pair<int, int>
的特化。这是一个非常简单的示例,展示了如何定义这个特化:
#include <utility>
#include <unordered_set>
namespace std
{
template<>
struct hash<std::pair<int, int>>
{
size_t operator () (std::pair<int, int> const& p)
{
// A bad example of computing the hash,
// rather replace with something more clever
return (std::hash<int>()(p.first) + std::hash<int>()(p.second));
}
};
}
class A
{
private:
// This won't give you problems anymore
std::unordered_set< std::pair<int, int> > u_edge_;
};
#include <cassert>
#include <cstdint>
#include <unordered_set>
#include <utility>
struct IntPairHash {
std::size_t operator()(const std::pair<uint32_t, uint32_t> &p) const {
assert(sizeof(std::size_t)>=8); //Ensure that std::size_t, the type of the hash, is large enough
//Shift first integer over to make room for the second integer. The two are
//then packed side by side.
return (((uint64_t)p.first)<<32) | ((uint64_t)p.second);
}
};
int main(){
std::unordered_set< std::pair<uint32_t, uint32_t>, IntPairHash> uset;
uset.emplace(10,20);
uset.emplace(20,30);
uset.emplace(10,20);
assert(uset.size()==2);
}
std::pair<int, int>>
的哈希函数。例如:struct bad_hash
{
std::size_t operator()(const std::pair<int,int>& p) const
{
return 42;
}
};
....
std::unordered_set< std::pair<int, int>, bad_hash> u_edge_;
您还可以为std::hash<T>
专门化,以适用于std::hash<std::pair<int,int>>
,在这种情况下,您可以省略第二个模板参数。
std::unordered_set
,我认为可以安全地假设 OP 想要一个 C++11 的解决方案。 - juanchopanza要创建一个无序对集合,您可以创建自定义哈希函数或创建字符串的无序集合。
创建自定义哈希函数:创建自定义哈希取决于数据。因此,没有一种适用于所有情况的哈希函数。良好的哈希函数必须具有较少的冲突,因此在制作哈希函数时需要考虑冲突计数。
使用字符串:使用字符串非常简单,时间也较短。它还保证了很少或没有冲突。我们可以通过使用分隔符(字符或字符串)来表示对,而不是使用unordered_set<pair<int,int>>,我们使用unordered_set。下面给出的示例显示了如何使用分隔符(“;”)插入整数对。
auto StringPair = [](const pair<int, int>& x){return to_string(x.first) + ";" + to_string(x.second);}; unordered_set Set;
vector<pair<int, int>> Nums = {{1,2}, {2, 3}, {4, 5}, {1,2}};
for(auto & pair: Nums) { Set.insert(StringPair(pair)); }
只是想在这里加入我的两分钱,使用unordered_set需要指定外部哈希函数真的很奇怪。封装原则更倾向于在类内部有一个返回哈希值的'hash()'函数,而unordered_set会调用它。你应该有一个Hashable接口,你的类(在这种情况下是std::pair)将实现该接口。
我认为这是Java等语言采用的方法。不幸的是,C++没有遵循这种逻辑。你可以最接近地模仿它:
代码示例
class Point : public pair<int, int> {
public:
Point() {};
Point(int first, int second) : pair{first, second}{};
class Hash {
public:
auto operator()(const Point &p) const -> size_t {
return ((size_t)p.first) << 32 | ((size_t)p.second);
}
};
};
int main()
{
unordered_set< Point, Point::Hash > us;
Point mypoint(1000000000,1);
size_t res = Point::Hash()(mypoint);
cout<<"Hello World " << res << " " << mypoint.first;
return 0;
}
如果size_t是64位,int是32位,则使用的简单哈希函数有效,此时该哈希函数保证没有冲突并且是理想的。