自定义类实现Hash计算(C++实现)

给子定义类定义hash计算,是的可以使用标准库的散列容器 unordered_set 和 unordered_map,有多重方法实现:1)给标准库中的 hash / equal_to实例化一个自定义类的类型;2)自定义函数对象

公共部分,自定义类,自定义数据和测试函数

// 自定义销售类
class Sales_data {
    friend class std::hash; // 友元,便于访问数据进行hash计算
    friend class std::equal_to; // 友元,便于访问数据进行相等判断
public:
    Sales_data() = default; // 默认构造函数

    Sales_data(const string bn) : bookNo(bn), units_sold(0), revenue(0) {}

    Sales_data(const string bn, unsigned us, double re) : bookNo(bn), units_sold(us), revenue(re) {}

//private:
    std::string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
};
   // 测试数据
    vector salesData{Sales_data("book1"), Sales_data{"book2"},
                                 Sales_data("book3"), Sales_data("book4")};
    vector> salesDataPari{{Sales_data("book1"), 1},
                                                     {Sales_data{"book2"}, 2},
                                                     {Sales_data("book3"), 3},
                                                     {Sales_data("book4"), 4}};

    // 测试函数
    template
    void compareTest(const S &sduset, const M &sdumap) {
        // S unordered_set
        // M unordered_map
        assert(sduset.find(Sales_data("book1")) != sduset.end());
        assert(sduset.find(Sales_data("book3")) != sduset.end());
        assert(sduset.find(Sales_data("book5")) == sduset.end());

        assert(sdumap.count(Sales_data("book1")) == 1);
        assert(sdumap.count(Sales_data("book4")) == 1);
        assert(sdumap.count(Sales_data("book5")) == 0);

        assert(sdumap.find(Sales_data("book1")) != sdumap.end());
        assert(sdumap.find(Sales_data("book4")) != sdumap.end());
        assert(sdumap.find(Sales_data("book5")) == sdumap.end());

        assert(sdumap.find(Sales_data("book1"))->second == 1);
        assert(sdumap.find(Sales_data("book4"))->second != 5);
    }

1、给标准库中的 hash / equal_to实例化一个自定义类的类型

// 打开std命名空间,以便特例化std::hash / std::equal_to
namespace std {
    // 散列, hash值计算
    template<>
    struct hash {
        using result_type = std::size_t;
        using argument_type = Sales_data;

        std::size_t operator()(const Sales_data &rhs) const {
            return std::hash()(rhs.bookNo) ^
                   std::hash()(rhs.units_sold) ^
                   std::hash()(rhs.revenue);
        }
    };

    // 比较相等
    template<>
    struct equal_to {
        typedef Sales_data first_argument_type;
        typedef Sales_data second_argument_type;
        typedef bool result_type;

        bool operator()(const Sales_data &lhs, const Sales_data &rhs) const {
            return lhs.bookNo == rhs.bookNo &&
                   lhs.units_sold == rhs.units_sold &&
                   lhs.revenue == rhs.revenue;
        }
    };
}  // 关std闭命名空间, 注意,没有;

使用和测试

    void HashWithStd() {
        unordered_set sduset(salesData.cbegin(), salesData.cend());  // 用salesData初始化set
        unordered_map sdumap(salesDataPari.cbegin(), salesDataPari.cend());  // 用salesDataPari初始化map
        compareTest(sduset, sdumap); // 测试数据插入是否正常
        return;
    }

2、函数对象实现

    // 用函数对象实现hash
    class SalesDataHash {
    public:
        std::size_t operator()(const Sales_data &rhs) const {
            return std::hash()(rhs.bookNo) ^
                   std::hash()(rhs.units_sold) ^
                   std::hash()(rhs.revenue);
        }
    };

    class SalesDataEqual {
    public:
        bool operator()(const Sales_data &lhs, const Sales_data &rhs) const {
            return lhs.bookNo == rhs.bookNo &&
                   lhs.units_sold == rhs.units_sold &&
                   lhs.revenue == rhs.revenue;
        }
    };

使用和测试

    void HashWithFunctionObj() {
        unordered_set sduset(salesData.cbegin(), salesData.cend());
        unordered_map sdumap(salesDataPari.cbegin(),
                                                                             salesDataPari.cend());
        compareTest(sduset, sdumap);
        return;
    }

你可能感兴趣的:(Hash,c++,hash)