- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在尝试使用自定义类作为 unordered_map
的键,如下所示:
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;
class node;
class Solution;
class Node {
public:
int a;
int b;
int c;
Node(){}
Node(vector<int> v) {
sort(v.begin(), v.end());
a = v[0];
b = v[1];
c = v[2];
}
bool operator==(Node i) {
if ( i.a==this->a && i.b==this->b &&i.c==this->c ) {
return true;
} else {
return false;
}
}
};
int main() {
unordered_map<Node, int> m;
vector<int> v;
v.push_back(3);
v.push_back(8);
v.push_back(9);
Node n(v);
m[n] = 0;
return 0;
}
但是,g++ 给我以下错误:
In file included from /usr/include/c++/4.6/string:50:0,
from /usr/include/c++/4.6/bits/locale_classes.h:42,
from /usr/include/c++/4.6/bits/ios_base.h:43,
from /usr/include/c++/4.6/ios:43,
from /usr/include/c++/4.6/ostream:40,
from /usr/include/c++/4.6/iostream:40,
from 3sum.cpp:4:
/usr/include/c++/4.6/bits/stl_function.h: In member function ‘bool std::equal_to<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = Node]’:
/usr/include/c++/4.6/bits/hashtable_policy.h:768:48: instantiated from ‘bool std::__detail::_Hash_code_base<_Key, _Value, _ExtractKey, _Equal, _H1, _H2, std::__detail::_Default_ranged_hash, false>::_M_compare(const _Key&, std::__detail::_Hash_code_base<_Key, _Value, _ExtractKey, _Equal, _H1, _H2, std::__detail::_Default_ranged_hash, false>::_Hash_code_type, std::__detail::_Hash_node<_Value, false>*) const [with _Key = Node, _Value = std::pair<const Node, int>, _ExtractKey = std::_Select1st<std::pair<const Node, int> >, _Equal = std::equal_to<Node>, _H1 = std::hash<Node>, _H2 = std::__detail::_Mod_range_hashing, std::__detail::_Hash_code_base<_Key, _Value, _ExtractKey, _Equal, _H1, _H2, std::__detail::_Default_ranged_hash, false>::_Hash_code_type = long unsigned int]’
/usr/include/c++/4.6/bits/hashtable.h:897:2: instantiated from ‘std::_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, __cache_hash_code, __constant_iterators, __unique_keys>::_Node* std::_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, __cache_hash_code, __constant_iterators, __unique_keys>::_M_find_node(std::_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, __cache_hash_code, __constant_iterators, __unique_keys>::_Node*, const key_type&, typename std::_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, __cache_hash_code, __constant_iterators, __unique_keys>::_Hash_code_type) const [with _Key = Node, _Value = std::pair<const Node, int>, _Allocator = std::allocator<std::pair<const Node, int> >, _ExtractKey = std::_Select1st<std::pair<const Node, int> >, _Equal = std::equal_to<Node>, _H1 = std::hash<Node>, _H2 = std::__detail::_Mod_range_hashing, _Hash = std::__detail::_Default_ranged_hash, _RehashPolicy = std::__detail::_Prime_rehash_policy, bool __cache_hash_code = false, bool __constant_iterators = false, bool __unique_keys = true, std::_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, __cache_hash_code, __constant_iterators, __unique_keys>::_Node = std::__detail::_Hash_node<std::pair<const Node, int>, false>, std::_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, __cache_hash_code, __constant_iterators, __unique_keys>::key_type = Node, typename std::_Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, __cache_hash_code, __constant_iterators, __unique_keys>::_Hash_code_type = long unsigned int]’
/usr/include/c++/4.6/bits/hashtable_policy.h:546:53: instantiated from ‘std::__detail::_Map_base<_Key, _Pair, std::_Select1st<_Pair>, true, _Hashtable>::mapped_type& std::__detail::_Map_base<_Key, _Pair, std::_Select1st<_Pair>, true, _Hashtable>::operator[](const _Key&) [with _Key = Node, _Pair = std::pair<const Node, int>, _Hashtable = std::_Hashtable<Node, std::pair<const Node, int>, std::allocator<std::pair<const Node, int> >, std::_Select1st<std::pair<const Node, int> >, std::equal_to<Node>, std::hash<Node>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, false, false, true>, std::__detail::_Map_base<_Key, _Pair, std::_Select1st<_Pair>, true, _Hashtable>::mapped_type = int]’
3sum.cpp:149:5: instantiated from here
/usr/include/c++/4.6/bits/stl_function.h:209:23: error: passing ‘const Node’ as ‘this’ argument of ‘bool Node::operator==(Node)’ discards qualifiers [-fpermissive]
make: *** [threeSum] Error 1
我想,我需要告诉 C++ 如何散列类 Node
,但是,我不太确定该怎么做。我怎样才能完成这个任务?
最佳答案
能够使用std::unordered_map
(或其他无序关联容器之一)具有用户定义的键类型,您需要定义两件事:
一个散列函数;这必须是一个覆盖 operator()
的类并计算给定键类型对象的哈希值。一种特别直接的方法是专门化 std::hash
您的 key 类型的模板。
一个相等比较函数;这是必需的,因为散列不能依赖于散列函数将始终为每个不同的键提供唯一的散列值这一事实(即,它需要能够处理冲突),因此它需要一种方法来比较两个给定的键精确匹配。您可以将其实现为覆盖 operator()
的类,或作为 std::equal
的特化, 或者 – 最简单的 – 通过重载 operator==()
为您的 key 类型(就像您已经做的那样)。
散列函数的困难在于,如果您的键类型由多个成员组成,您通常会让散列函数计算各个成员的散列值,然后以某种方式将它们组合成整个对象的一个散列值。为了获得良好的性能(即,很少发生冲突),您应该仔细考虑如何组合各个散列值,以确保避免经常为不同的对象获得相同的输出。
散列函数的一个相当好的起点是使用移位和按位异或来组合各个散列值的散列函数。例如,假设这样的键类型:
struct Key
{
std::string first;
std::string second;
int third;
bool operator==(const Key &other) const
{ return (first == other.first
&& second == other.second
&& third == other.third);
}
};
这是一个简单的哈希函数(改编自 cppreference example for user-defined hash functions 中使用的函数):
namespace std {
template <>
struct hash<Key>
{
std::size_t operator()(const Key& k) const
{
using std::size_t;
using std::hash;
using std::string;
// Compute individual hash values for first,
// second and third and combine them using XOR
// and bit shifting:
return ((hash<string>()(k.first)
^ (hash<string>()(k.second) << 1)) >> 1)
^ (hash<int>()(k.third) << 1);
}
};
}
有了这个,你可以实例化一个 std::unordered_map
对于键类型:
int main()
{
std::unordered_map<Key,std::string> m6 = {
{ {"John", "Doe", 12}, "example"},
{ {"Mary", "Sue", 21}, "another"}
};
}
它会自动使用std::hash<Key>
如上定义的哈希值计算,以及 operator==
定义为 Key
的成员函数用于平等检查。
如果你不想在 std
中特化模板命名空间(尽管在这种情况下它是完全合法的),您可以将哈希函数定义为一个单独的类并将其添加到映射的模板参数列表中:
struct KeyHasher
{
std::size_t operator()(const Key& k) const
{
using std::size_t;
using std::hash;
using std::string;
return ((hash<string>()(k.first)
^ (hash<string>()(k.second) << 1)) >> 1)
^ (hash<int>()(k.third) << 1);
}
};
int main()
{
std::unordered_map<Key,std::string,KeyHasher> m6 = {
{ {"John", "Doe", 12}, "example"},
{ {"Mary", "Sue", 21}, "another"}
};
}
如何定义更好的哈希函数?如上所述,定义一个好的散列函数对于避免冲突和获得良好的性能很重要。对于一个真正好的结果,您需要考虑所有字段的可能值的分布,并定义一个哈希函数,该函数将该分布转换到尽可能广泛且均匀分布的可能结果空间。
这可能很困难;上面的异或/位移方法可能是一个不错的开始。为了更好的开始,您可以使用 hash_value
和 hash_combine
来自 Boost 库的函数模板。前者的行为与 std::hash
类似。对于标准类型(最近还包括元组和其他有用的标准类型);后者可帮助您将各个散列值合并为一个。这是使用 Boost 辅助函数重写的哈希函数:
#include <boost/functional/hash.hpp>
struct KeyHasher
{
std::size_t operator()(const Key& k) const
{
using boost::hash_value;
using boost::hash_combine;
// Start with a hash value of 0 .
std::size_t seed = 0;
// Modify 'seed' by XORing and bit-shifting in
// one member of 'Key' after the other:
hash_combine(seed,hash_value(k.first));
hash_combine(seed,hash_value(k.second));
hash_combine(seed,hash_value(k.third));
// Return the result.
return seed;
}
};
这是一个不使用 boost 的重写,但使用了组合哈希的好方法:
namespace std
{
template <>
struct hash<Key>
{
size_t operator()( const Key& k ) const
{
// Compute individual hash values for first, second and third
// http://stackoverflow.com/a/1646913/126995
size_t res = 17;
res = res * 31 + hash<string>()( k.first );
res = res * 31 + hash<string>()( k.second );
res = res * 31 + hash<int>()( k.third );
return res;
}
};
}
关于C++ unordered_map 使用自定义类类型作为键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49807060/
我目前正在寻找 std::map 的更好替代方案,并且遇到了帖子标题中提到的类。有人可以阐明它们之间的区别,不是在性能/API 方面,而是在它们与当前和 future 的通信标准相关的地方。 最佳答案
我正在尝试使用一个 unordered_map 和另一个 unordered_map 作为键(自定义哈希函数)。我还添加了一个自定义的 equal 函数,尽管它可能并不需要。 代码没有达到我的预期,但
关闭。这个问题是not reproducible or was caused by typos .它目前不接受答案。 这个问题是由于错别字或无法再重现的问题引起的。虽然类似的问题可能是on-topi
我正在尝试从 unordered_map 中返回 unordered_map 的拷贝。 下面的代码更清楚地说明了我的问题: typedef std::unordered_map Foo; typede
我有一个类型为unordered_map的容器,我想确认要向 map 添加元素时应使用哪个版本。我希望它使用新呈现的旧值覆盖旧的值(如果存在),如果不存在则仅添加它。 我看到insert会在元素退出时
所以我试图将 unordered_map 设置为另一个 unordered_map 的值。 现在我遇到了无法将值放入第二个 unordered_map 的问题。 我的代码看起来像这样。 std::
我有一个数据结构,它是 unordered_map 的 unordered_map: typedef std::unordered_map map1; typedef std::unordered_m
我们正在用 C++ 为学校开发一个游戏项目。我负责 map 对象,它将包含炸弹、玩家、墙壁和盒子等实体。我的 map 中有 3 个容器: 玩家的 std::list(多个玩家可以站在同一个盒子上)。
我正在使用 unordered_maps 的 unordered_map,这样我就可以使用“多键”语法来引用元素: my_map[k1][k2]。 有没有一种方便的方法可以在尝试访问之前使用相同的“多
假设我有一个 unordered_map 定义如下: unordered_map> f_table; f_table[1][3] = 10; f_table[1][2] = 1; f_table[1]
我正在 interviewbit.com 上解决竞争性编程问题我基本上使用 unordered_map 来跟踪访问过的数字。当我使用 operator[] 时,我的代码无法及时执行,但是当我使用 fi
我有一张 map ,如下所示。 struct B { int b1; int b2; int b3; }; struct A { B a1; B a2; }; unordered
我有以下数据结构问题?你能帮帮我吗?所以我的要求是在我将新数据项添加到此 map 时将此数据结构初始化为默认值。 我怎样才能有效地做到这一点? 对于我要添加的每个条目,我需要将 a1、a2、a3 设置
对于我的下一个任务,我需要使用一个非常大的散列;因为我有一个旧的编译器,所以我不能使用 C++0x std::unordered_map。理想情况下,我需要调用 reserve 为大量元素提前腾出空间
我不明白为什么这个简短示例中的第二个代码块无法正确编译。我的理解是 <> 中的第二个参数表示值,它不需要是唯一的。为什么第二个代码块抛出编译器错误,我需要做什么来补救它? // Unordered M
这段代码运行成功,结果为“Character Found”。 unordered_map mp; mp['a'] = 'b'; char b='b'; if(mp['a'] && mp['a'] ==
std::unordered_map::emplace和std::unordered_map::insert在C++中有什么区别? 最佳答案 unordered_map::insert 将键值对复制或
哪个更有效率?有什么好的基准吗? 最佳答案 C++11 的 std::unordered_map 规范类似于基于 tr1::unordered_map 的 boost::unordered_map。话
使用 gcc 4.8.1 和 libboost 1.53,根据我用于编译代码的优化级别,我得到了不同的结果。作为更大程序的一部分,函数 insertValues 对相同的 a、key 和 value
我正在尝试使用 boost::mulprecision 类型创建一个 STL(或 boost)unordered_map,例如cpp_int 但 gcc 在尝试将元素插入此容器后抛出错误。 #incl
我是一名优秀的程序员,十分优秀!