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

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

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

// 自定义销售类
class Sales_data {
    friend class std::hash<Sales_data>; // 友元,便于访问数据进行hash计算
    friend class std::equal_to<Sales_data>; // 友元,便于访问数据进行相等判断
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<Sales_data> salesData{Sales_data("book1"), Sales_data{"book2"},
                                 Sales_data("book3"), Sales_data("book4")};
    vector<std::pair<Sales_data, int>> salesDataPari{{Sales_data("book1"), 1},
                                                     {Sales_data{"book2"}, 2},
                                                     {Sales_data("book3"), 3},
                                                     {Sales_data("book4"), 4}};

    // 测试函数
    template<typename S, typename M>
    void compareTest(const S &sduset, const M &sdumap) {
        // S unordered_set<Sales_data>
        // M unordered_map<Sales_data, int>
        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<Sales_data> {
        using result_type = std::size_t;
        using argument_type = Sales_data;

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

    // 比较相等
    template<>
    struct equal_to<Sales_data> {
        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<Sales_data> sduset(salesData.cbegin(), salesData.cend());  // 用salesData初始化set
        unordered_map<Sales_data, int> 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<string>()(rhs.bookNo) ^
                   std::hash<unsigned>()(rhs.units_sold) ^
                   std::hash<double>()(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<Sales_data, SalesDataHash, SalesDataEqual> sduset(salesData.cbegin(), salesData.cend());
        unordered_map<Sales_data, int, SalesDataHash, SalesDataEqual> sdumap(salesDataPari.cbegin(),
                                                                             salesDataPari.cend());
        compareTest(sduset, sdumap);
        return;
    }

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值