我如何使用unordered_set?

时间:2013-08-07 08:17:38

标签: c++ stl set unordered-set

我正在尝试定义这样的unordered_set:

unordered_set<Point> m_Points;

当我编译它时,我收到以下错误:

  

C ++标准不提供此类型的哈希值。

班级Point

class Point{
    private:
        int x, y;
    public:
        Point(int a_x, int a_y)
            : x(a_x), y(a_y)
        {}
        ~Point(){}

        int getX()const { return x; }
        int getY()const { return y; }

        bool operator == (const Point& rhs) const{
            return x == rhs.x && y == rhs.y;
        }

        bool operator != (const Point& rhs) const{
            return !(*this == rhs);
        }
};
  • 我如何/在哪里为 Point
  • 定义哈希函数
  • 2D点的好散列函数是什么?

1 个答案:

答案 0 :(得分:24)

std::unordered_set要求您编写hash functions来存储和查找自己的类型。

std命名空间中的基类型和许多类型在std::hash<Key>中都有这样的哈希函数。这些函数遵循certain rules

  1. 接受Key类型的单个参数。

  2. 返回类型size_t的值,表示参数的哈希值。

  3. 调用时不会抛出异常。

  4. 对于两个相等的参数k1k2 std::hash<Key>()(k1) == std::hash<Key>()(k2)

  5. 对于不相等的两个不同参数k1k2std::hash<Key>()(k1) == std::hash<Key>()(k2)应该非常小,接近1.0/std::numeric_limits<size_t>::max()的概率。

  6. 既然我们已经完成了定义,那么让我们考虑一下你的点结构会有什么好的哈希函数。有一个request std::pair(它与点结构非常相似)得到了一个哈希函数,但不幸的是,它没有进入C ++ 11标准。

    但我们很幸运:太棒了,当然,你基本上已经find the answer了。请注意,您不必自己散列整数,因为std::hash已经具有专门化。因此,根据this answer

    ,让我们深入研究哈希函数
    namespace std
    {
        template <>
        struct hash<Point>
        {
            size_t operator()(Point const & x) const noexcept
            {
                return (
                    (51 + std::hash<int>()(x.getX())) * 51
                    + std::hash<int>()(x.getY())
                );
            }
        };
    }
    

    我们已经完成了。