当前位置:   article > 正文

unordered_map自定义类重写hash函数对象与比较函数对象_c++ unordered map 自定义哈希函数

c++ unordered map 自定义哈希函数

在一些无序查找问题中,c++一般采用STL中的unordered_map作为存储结构,底层原理主要是以哈希桶的方式存储数据,使得查找时间复杂度接近常数级,原理不细说,这里主要讲使用unordered_map存储自定义类时,需要我们自定义key的hash函数对象,并自定义比较函数对象。

对于unordered_map官方定义:

  1. template<class Key,
  2. class T,
  3. class Hash = std::hash<Key>,
  4. class Pred = std::equal_to<Key>,
  5. class Alloc = std::allocator<std::pair<const Key, Ty> > >
  6. class unordered_map;
  7. > class unordered_map

其中参数 Key 表示键的类型, T 表示键映射到哈希表中值的类型,Hash 是接受一个参数,且类型与 Key 兼容的函数对象,返回值为 T 类型,Pred 为 接受两个参数,且类型与 Key 兼容的函数对象,返回值为 bool。需要注意的是,这两个函数对象的参数都为 const 引用,函数都是 const 。

举例说明:自定义两个类,article_id 与 article,分别作为键与值

类 article_id

  1. // 类article_id
  2. struct article_id
  3. {
  4. friend std::ostream & operator<<(std::ostream &os, const article_id &a);
  5. std::string brand;
  6. int id;
  7. article_id(const std::string &b, int id) : brand(b), id(id) { }
  8. };

重载 << 运算符

  1. std::ostream & operator<<(std::ostream &os, const article_id &a)
  2. {
  3. os << "(" << a.brand << ")" << a.id;
  4. return os;
  5. }

 类 article

  1. // 类 article
  2. class article
  3. {
  4. friend std::ostream & operator << (std::ostream &os, const article &a);
  5. public:
  6. article(const std::string &b, const std::string &m, const std::string &d) :
  7. brand(b), model(m), description(d) { }
  8. private:
  9. std::string brand;
  10. std::string model;
  11. std::string description;
  12. };

重载 << 运算符

  1. std::ostream & operator << (std::ostream &os, const article &a)
  2. {
  3. os << "Brand: " << a.brand << "; Model: " << a.model
  4. << "; Description: " << a.description;
  5. return os;
  6. }

自定义 hash 函数对象

  1. template <class T>
  2. class article_hash
  3. {
  4. public:
  5. long operator()(const article_id &x) const
  6. {
  7. std::hash<T> z;
  8. return z(x.brand) * 100 + x.id;
  9. }
  10. };

自定义比较函数对象

  1. class article_equal_to
  2. {
  3. public:
  4. bool operator () (const article_id &a, const article_id &b) const
  5. {
  6. return a.brand == b.brand && a.id == b.id;
  7. }
  8. };

函数对象,其实就是重载了operator()的 类,这样的类统称为函数对象类,它的使用形式像函数调用,实际也执行了函数调用。

main函数:

  1. template <class T>
  2. void show(const T & x)
  3. {
  4. for (auto &i : x)
  5. {
  6. std::cout << i.first << "; " << i.second << std::endl;
  7. }
  8. }
  9. int main()
  10. {
  11. std::unordered_map<article_id, article, article_hash<std::string>, article_equal_to> x;
  12. x.insert(std::make_pair(article_id("acme", 1), article("acme", "tv", "Acme TV")));
  13. x.insert(std::make_pair(article_id("foo", 4), article("foo", "phone", "fooPhone")));
  14. show(x);
  15. return 0;
  16. }

PS:除了使用自定义函数对象的方法,我们也可以使用直接自定义函数的方式

  1. 自定义 hash 函数
  2. 自定义比较函数
  3. 像unordered_map<>中传入函数指针,可以使用c++11 decltype特性,
    std::unordered_map<article_id, article, decltype(hasher) *, decltype(equal_to) *> x;

PS again: 上文中的例子是参考一个大佬的一篇文章,只是找不到网址了,以后找到连接会更新到后面。

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号