C++无序向量集

43
可以在C++中创建一个无序向量集吗?类似这样的东西。
std::unordered_set<std::vector<int>> s1;

因为我知道标准库中的“set”类可以做到这一点,但似乎对于无序版本不起作用。 谢谢

更新: 这正是我正在尝试使用的代码

typedef int CustomerId;
typedef std::vector<CustomerId> Route;
typedef std::unordered_set<Route> Plan;

// ... in the main
Route r1 = { 4, 5, 2, 10 };
Route r2 = { 1, 3, 8 , 6 };
Route r3 = { 9, 7 };
Plan p = { r1, r2 };

如果我使用set是可以的,但当我尝试使用无序版本时,会收到编译错误。

main.cpp:46:11: error: non-aggregate type 'Route' (aka 'vector<CustomerId>') cannot be initialized with an initializer list
    Route r3 = { 9, 7 };

1
你是不是想要类似 std::unordered_set<std::vector<int>> 这样的东西? - πάντα ῥεῖ
它为什么不工作?你遇到了什么问题? - Some programmer dude
1
“不起作用”是什么意思?请发布一个SSCCE - Praetorian
1
是的,您可以拥有一个 std::unordered_set<std::vector<some_type>> - NathanOliver
1
@CattaniSimone 嗯...什么意思?你使用的编译器是什么,r3失败了,但Plan构造函数没有失败? - Barry
显示剩余3条评论
2个回答

53
当然可以。不过你需要自己创建一个哈希函数,因为默认的哈希函数 (std::hash<std::vector<int>>) 是没有被实现的。例如,根据这个答案,我们可以构建如下代码:
struct VectorHash {
    size_t operator()(const std::vector<int>& v) const {
        std::hash<int> hasher;
        size_t seed = 0;
        for (int i : v) {
            seed ^= hasher(i) + 0x9e3779b9 + (seed<<6) + (seed>>2);
        }
        return seed;
    }
};

接下来:

using MySet = std::unordered_set<std::vector<int>, VectorHash>;

如果您愿意,也可以为此类型添加一个std::hash<T>的专业化,作为替代选择(请注意,这可能会导致std::vector<int>未定义行为,但对于用户定义的类型肯定是可以的):

namespace std {
    template <>
    struct hash<std::vector<int>> {
        size_t operator()(const vector<int>& v) const {
            // same thing
        }
    };
}

using MySet = std::unordered_set<std::vector<int>>;

2
第二部分可能是未定义行为。就库而言,我认为std::vector<int>不算作用户定义类型。 - T.C.
1
为什么不使用默认的(std::hash<std::vector<int>>)哈希函数? - Divyansh
3
标准库中没有std::hash<std::vector<int>>这个函数,暂不支持。 - Barry
如果没有默认哈希函数,那么std::set<vector<int>>是如何工作的呢? - NanoNi
2
@NanoNi std::set 不是哈希表,而是二叉树。它使用 < - Barry

2

除了自定义哈希函数,Boost还为许多标准库类型提供了哈希函数。在您的情况下,这应该可以使用:

#include <boost/container_hash/hash.hpp>

std::unordered_set<
  std::vector<int>,
  boost::hash<std::vector<int>>
> s1;

参考:https://www.boost.org/doc/libs/1_78_0/doc/html/hash/reference.html 在旧的 Boost 版本中,头文件名为 boost/functional/hash.hpp。针对 IT 技术方面的内容进行翻译,敬请留意。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接