如何声明存储vector<unordered_set<int>>的set/unordered_set并解决相关问题
std::vector<std::unordered_set<int>>去重的容器适配问题 我需要声明一个变量存储std::vector<std::unordered_set<int>>类型的元素以实现自动去重,考虑用std::set或std::unordered_set,但遇到两个问题:
- 尝试用
std::unordered_set声明时:
std::unordered_set<std::vector<std::unordered_set<int>>, \ boost::hash<std::vector<std::unordered_set<int>>>> Variable1;
出现错误:boost::hash_value - none of the 3 overloads could convert all the argument types,想知道有没有boost或非boost的合适哈希函数?
2. 用std::set声明时:
std::set<std::vector<std::unordered_set<int>>> Variable2;
需要为std::vector<std::unordered_set<int>>实现<比较运算符,有没有预定义的实现方式?
一、为std::vector<std::unordered_set<int>>提供哈希函数(适配std::unordered_set)
Boost方式
Boost的hash默认不支持哈希std::unordered_set,你需要手动为std::unordered_set<int>扩展哈希实现,让boost::hash能递归处理vector:
#include <boost/functional/hash.hpp> #include <unordered_set> #include <vector> namespace boost { template<typename T> std::size_t hash_value(const std::unordered_set<T>& s) { std::size_t seed = 0; for (const auto& elem : s) { boost::hash_combine(seed, elem); } return seed; } } // 现在可正常声明 std::unordered_set<std::vector<std::unordered_set<int>>, boost::hash<std::vector<std::unordered_set<int>>>> Variable1;
Boost的hash本身支持vector,只要元素类型能被哈希,就能自动处理整个容器的哈希计算。
非Boost方式(标准库自定义哈希)
自己实现哈希结构体,分别处理unordered_set<int>和嵌套的vector:
#include <unordered_set> #include <vector> #include <functional> struct HashUnorderedSet { std::size_t operator()(const std::unordered_set<int>& s) const { std::size_t seed = 0; for (int num : s) { std::hash<int> hasher; seed ^= hasher(num) + 0x9e3779b9 + (seed << 6) + (seed >> 2); } return seed; } }; struct HashVectorOfUnorderedSets { std::size_t operator()(const std::vector<std::unordered_set<int>>& vec) const { std::size_t seed = 0; HashUnorderedSet set_hasher; for (const auto& s : vec) { seed ^= set_hasher(s) + 0x9e3779b9 + (seed << 6) + (seed >> 2); } return seed; } }; // 声明方式 std::unordered_set<std::vector<std::unordered_set<int>>, HashVectorOfUnorderedSets> Variable1;
这里用标准库std::hash<int>,通过0x9e3779b9(黄金分割数,减少哈希碰撞)组合每个元素的哈希值,生成整个容器的最终哈希。
二、为std::vector<std::unordered_set<int>>实现<比较运算符(适配std::set)
标准库已经为std::vector提供了默认的<运算符(按顺序逐个比较元素),但std::unordered_set是无序容器,标准库不提供默认的<比较。你只需要给unordered_set<int>实现一个全序比较,vector的默认比较就能生效:
#include <unordered_set> #include <vector> #include <algorithm> bool operator<(const std::unordered_set<int>& lhs, const std::unordered_set<int>& rhs) { if (lhs.size() != rhs.size()) { return lhs.size() < rhs.size(); } // 转成有序vector再比较,保证全序关系 std::vector<int> lhs_vec(lhs.begin(), lhs.end()); std::vector<int> rhs_vec(rhs.begin(), rhs.end()); std::sort(lhs_vec.begin(), lhs_vec.end()); std::sort(rhs_vec.begin(), rhs_vec.end()); return lhs_vec < rhs_vec; } // 现在可直接声明set std::set<std::vector<std::unordered_set<int>>> Variable2;
逻辑很简单:先比较集合大小,大小不同直接按大小判断;大小相同就转成有序vector,用vector的默认比较得到稳定的全序关系,满足std::set的排序要求。
内容的提问来源于stack exchange,提问作者Tryer

