本文只介绍我们在C++中如何使用Hash这种数据结构达到我们编程的目的,有关Hash的概念和实现不做详谈。

C++11新增了一类散列容器包括unordered_set, unordered_map, unordered_multiset, unordered_multimap, 即之前熟悉的hash_set, hash_map等。

这类容器底层以哈希表实现之,通过unordered_map介绍下这类容器的使用。

unordered_map 是一个模板类,需要我们提供5个魔板参数。依次为:key值的类型, value值的类型,hash函数, 等价函数, 容器分配器。其中后三个有默认参数,那我们是不是只需要提供前2个模板参数就可以使用了呢? 不一定。当我们使用的key为内置类型时(如int, double, float, string等),后面三个默认模板参数在STL内有其特化版本,故可以直接进行使用。可一旦你的类为自定义类型, 其中的hash和equal就得由你自己提供。其实也不难理解, 假设你的对象是一块石头,石头怎么进行hash, 石头怎么怎么比大小呢?编译器当然不知道,这就需要你告诉编译器。下面我们对这2种情况分别举例说明。

(一)、当key为内置类型:

unordered_map<string, int> m_map;

当key为内置类型, 仅需提供key与value的类型便可运用。 其中hash<string> 与 equal <int> 均有特化版本,分配器对整个容器进行内存管理,这三个参数均为默认参数。

(二)、当key为自定义类型:

比如我们简单定义一个package类,里面仅有名字,电话2项数据。

class package
{
public:
string getName() const { return name; }
long long getPhone() const { return phone; } package(string m_name = , long long m_pNum = ); bool operator== (const package& p) const
{ return name == p.name &&
phone == p.phone;
}
private:
string name;
long long phone;
};

然后将原生hash包装使用下:

namespace std
{
template<>
struct hash<package>
{
size_t operator() (const package& s) const noexcept
{
return hash<decltype(s.getName())>()(s.getName()) +
hash<decltype(s.getPhone())>()(s.getPhone());
}
}; // 间接调用原生Hash.
}

或者可以借助借助boost库的hash_value:

 namespace std
{
template<>
struct hash<package>
{
size_t operator() (const package& s) const noexcept
{
auto t = make_tuple(s.getName(), s.getPhone());
size_t value = boost::hash_value(t);
return value; // make_tuple(s.getName(), s.getPhone()) 等价于 tuple<string, long long>()(s.getName(), s.getPhone())
}
}; // 间接调用原生Hash.
}

当我们把Hash函数(package的特化版本)和 等价函数 (操作符==重载)提供后, 便可使用自定义版本的unordered_map了:

unordered_map<package, int> m_map;

下面给出测试代码:

测试环境: VS2017

#include <iostream>
#include <unordered_map>
#include <string>
#include <algorithm>
//#include <boost/functional/hash.hpp> // 根据安装路径选择hash.hpp
#include <tuple> using namespace std; class package
{
public:
string getName() const { return name; }
long long getPhone() const { return phone; } package(string m_name = , long long m_pNum = ); bool operator== (const package& p) const
{ return name == p.name &&
phone == p.phone;
} private:
string name;
long long phone;
}; package::package(string m_name, long long m_pNum)
: name(m_name), phone(m_pNum) { } namespace std
{
template<>
struct hash<package>
{
size_t operator() (const package& s) const noexcept
{
return hash<decltype(s.getName())>()(s.getName()) +
hash<decltype(s.getPhone())>()(s.getPhone()); //auto t = make_tuple(s.getName(), s.getPhone());
//size_t value = boost::hash_value(t);
//return value; // make_tuple(s.getName(), s.getPhone()) 等价于 tuple<string, long long>()(s.getName(), s.getPhone())
}
}; // 间接调用原生Hash.
} int main()
{
unordered_map<package, int> m_map; package p1{ "Wang", };
package p2{ "Li", };
package p3{ "Zhang", };
package p4{ "Zhou", };
package p5{ "Wang", };
package p6{ "Wang", }; m_map[p1]++;
m_map[p2]++;
m_map[p3]++;
m_map[p4]++;
m_map[p5]++;
m_map[p6]++; cout << m_map.bucket(p1) << " ";
cout << m_map.bucket(p2) << " ";
cout << m_map.bucket(p3) << " ";
cout << m_map.bucket(p4) << " ";
cout << m_map.bucket(p5) << " ";
cout << m_map.bucket(p6) << " " << endl; return ;
}

关于C++中Hash的应用的更多相关文章

  1. IOS9.0中hash值的bug与解决方案

    事件起因 事情是这样的:产品上线发布,突然出现了问题.运营Gg过来反应,当场给露珠演示,运营同事的手机是iphone,bug确实是存在的.奇怪的是露珠用了其他iphone手机(借别人的,露珠的是吊死安 ...

  2. URL中 # (hash)的含义

    url中#(hash)的含义 hash 属性是一个可读可写的字符串,该字符串是 URL 的锚部分(从 # 号开始的部分) 1."#"代表网页中的一个位置.其右面的字符,就是该位置的 ...

  3. 关于HashMap中hash()函数的思考

    关于HashMap中hash()函数的思考 JDK7中hash函数的实现   static int hash(int h) { h ^= (h >>> 20) ^ (h >&g ...

  4. Vue-router 中hash模式和history模式的区别

    实际上存在三种模式: Hash: 使用URL的hash值来作为路由.支持所有浏览器. History: 以来HTML5 History API 和服务器配置.参考官网中HTML5 History模式 ...

  5. Vue中hash模式和history模式的区别

    vue-router 中hash模式和history模式. 在vue的路由配置中有mode选项,最直观的区别就是在hash模式下的地址栏里的URL夹杂着‘#’号 ,而history模式下没有.vue默 ...

  6. Webpack中hash与chunkhash的区别,以及js与css的hash指纹解耦方案

    文件的hash指纹通常作为前端静态资源实现增量更新的方案之一,Webpack是目前最流行的开源编译工具之一,其强大的功能也带来很多坑(当然,大部分麻烦其实都可以在官方文档中找到答案). 比如,在Web ...

  7. Java中hashCode()方法以及HashMap()中hash()方法

    Java的Object类中有一个hashCode()方法: public final native Class<?> getClass(); public native int hashC ...

  8. ruby中Hash排序

    当values都是整形时,按照Hash的Values排序: h = {'a'=>1,'b'=>2,'c'=>5,'d'=>4} h.sort {|a,b| a[1]<=& ...

  9. 10g中HASH GROUP BY引起的临时表空间不足

    原本在9i上可以顺利完成的CTAS脚本,迁移到10g后运行总是报“ORA-1652: unable to extend temp segment by 128 in tablespace TS_HQY ...

  10. Redis中hash表中的field的value自增可以用hincrby

    Redis HINCRBY命令用于增加存储在字段中存储由增量键哈希的数量.如果键不存在,新的key被哈希创建.如果字段不存在,值被设置为0之前进行操作. 回复整数,字段的增值操作后的值. redis ...

随机推荐

  1. vmware中centos6.7系统图形化安装Oracle显示乱码问题解决

    root下: 修改环境属性  vi /etc/sysconfig/i18n LANG="en_US.UTF-8 1.在每次调用图形界面以前,我们使用export临时设置LANG(ORACLE ...

  2. Axure RP 9 Mac正式汉化版安装教程

    Axure RP9 汉化版是mac平台上一款交互式原型设计神器,是专为UX专业人员和业务分析师设计的专业网站原型设计工具!可以帮助他们快速创建应用程序和网站的线框,原型和规格!新功能包括一系列广泛的改 ...

  3. 编程类-----matlab基础语法复习(1)

    2019年美赛随笔记录: 具体功能:基础语法+基本运算+画图+矩阵+excel读取....... 所遇问题及其解决方案:         1.   que:matlab中plot画图无法复制下来图片? ...

  4. webpack4 系列教程(十六):开发模式和生产模式·实战

    好文章 https://www.jianshu.com/p/f2d30d02b719

  5. [CTF] RSA共模攻击

    from gmpy2 import * import libnum n = 0x00b0bee5e3e9e5a7e8d00b493355c618fc8c7d7d03b82e409951c182f398 ...

  6. 每天一套题打卡|河南省第十届ACM/ICPC

    A.谍报分析 题意:请你编程,快速统计出频率高的前十个单词. 思路:字符串输入,map哈希表map<string,int >记录每个单词出现的次数,pair重载优先级 #include&l ...

  7. hdu2159 FATE----完全背包

    标准完全背包板子,动态方程为dp[j][x]=max(dp[j][x],dp[j-c[i]][x-1]+a[i]); 其中,dp[j][x]表示花费j点耐心杀x个怪所能得到的最大经验值. 具体代码如下 ...

  8. 使用 pm2 优雅的部署 node 程序

    使用 pm2 优雅的部署 node 程序 # 启动并监控名字为 XXX 的 npm run start:dev 命令 pm2 start npm --watch --name XXX -- run s ...

  9. LINQ to Entities does not recognize the method 'System.DateTime AddDays(Double)' method, and this method cannot be translated into a store expression.

    NormalSubmission=analysis.Count(x=>x.FinishTime<= endTime.AddDays(1))报错linq不能识别 => var endT ...

  10. Vue-admin工作整理(三):路由

    1.router-link和router-view组件 router-link组件实际上是封装了一个a标签(链接标签),里面有一个重要属性:“to”,它的值是一个路径,其路径对应的渲染组件,要在路由列 ...