0x10基础数据结构-(5)-Hash
如果题目已知了要统计的数据的范围,并且不离散不太大,可以直接用数组统计,不用解决Hash冲突,更快
Hash 还有这样的初始化方法,很优雅,像python的Counters
https://leetcode.cn/problems/make-array-zero-by-subtracting-equal-amounts/
unordered_set s(nums.begin(), nums.end());
复合类型作为hash的Key
std::pair
是标准模板库(STL)中定义的模板类,用于组合两个元素。
std::tuple
是标准模板库(STL)中定义的模板类,用于组合三个及以上元素。
struct
结构体或class
类是用户自定义类型,可以由多个数据成员组成,每个成员可以是不同类型。
这些复合类型不能直接作为Hash Table的key来使用。
pair
std::pair
表示一个有序的、固定大小的、两个值的元组,每个值可以有不同的类型。
#include <unordered_map>
#include <functional> // std:hash
struct PairHash {
template<typename T1, typename T2>
std::size_t operator()(const std::pair<T1, T2>& pair) const {
return std::hash<T1>{}(pair.first) ^
std::hash<T2>{}(pair.second);
}
};
std::unordered_map<std::pair<int, int>, double, PairHash> myMap;
tuple
std::tuple
表示一个有序的、固定大小的、多个值的元组,每个值可以有不同的类型。
#include <unordered_map>
#include <functional> // std:hash
struct TupleHash {
template<typename... T>
std::size_t operator()(const std::tuple<T...>& tup) const {
return std::hash<std::string>{}(std::get<0>(tup)) ^
std::hash<std::string>{}(std::get<1>(tup)) ^
std::hash<std::string>{}(std::get<2>(tup));
}
};
std::unordered_map<std::tuple<int, int, std::string>, double, TupleHash> myMap;
struct / class
结构体作为hash表的key,除了要像std::pair
、std:tuple
那样实现hash函数,还要实现相等性比较函数:
#include <unordered_map>
#include <functional> // std:hash
struct Person {
std::string name;
int age;
std::string address;
};
// 组合哈希函数
struct PersonHash {
std::size_t operator()(const Person& p) const {
std::size_t nameHash = std::hash<std::string>{}(p.name);
std::size_t ageHash = std::hash<int>{}(p.age);
std::size_t addressHash = std::hash<std::string>{}(p.address);
return nameHash ^ (ageHash << 1) ^ (addressHash << 2);
}
};
// 相等性比较函数
struct PersonEqual {
bool operator()(const Person& p1, const Person& p2) const {
return p1.name == p2.name && p1.age == p2.age && p1.address == p2.address;
}
};
std::unordered_map<Person, std::string, PersonHash, PersonEqual> peopleMap;
也可以用另一种函数:
// 旋转哈希函数
struct PersonHash {
std::size_t operator()(const Person& p) const {
std::size_t nameHash = std::hash<std::string>{}(p.name);
std::size_t ageHash = std::hash<int>{}(p.age);
std::size_t addressHash = std::hash<std::string>{}(p.address);
const std::size_t rotateBits = sizeof(std::size_t) / 2; // 旋转的位数,这里假设是std::size_t的一半
nameHash = (nameHash << rotateBits) | (nameHash >> (sizeof(nameHash) * 8 - rotateBits));
ageHash = (ageHash << rotateBits) | (ageHash >> (sizeof(ageHash) * 8 - rotateBits));
addressHash = (addressHash << rotateBits) | (addressHash >> (sizeof(addressHash) * 8 - rotateBits));
return nameHash ^ ageHash ^ addressHash;
}
};
本博客所有文章均采用 CC BY-NC-SA 4.0 协议 ,禁止商用,转载请注明出处!