最近在刷题以及做编程练习的作业时经常会用到哈希表,碰到一些想用的函数时每次都看别人的博客,现结合别人的博客对哈希表做个总结。

本篇博客的主要内容如下

  • 1. 哈希表的定义
  • 2. 如何使用STL库中的哈希表
  • 3. STL中哈希表的常用函数

1. 哈希表的定义

(1)哈希表的作用
    哈希表就是在关键字和存储位置之间建立对应关系,使得元素的查找可以以O(1)的效率进行, 其中关键字和存储位置之间是通过散列函数建立关系,记为: Loc(i)=Hash(keyi)。Loc(i) = Hash(key_i)。Loc(i)=Hash(keyi​)。

(2) 常见的散列函数
    1)线性定址法:直接取关键字的某个线性函数作为存储地址,散列函数为:Hash(key)=a×key+bHash(key) = a × key + bHash(key)=a×key+b
    2)除留余数法:将关键字对某一小于散列表长度的数p取余的结果作为存储地址,散列函数为:Hash(key)=keymodpHash(key) = key \;mod \; pHash(key)=keymodp
    3)平方取中法:对关键字取平方,然后将得到结果的中间几位作为存储地址;
    4)折叠法:将关键字分割为几部分,然后将这几部分的叠加和作为存储地址。
(3) 地址冲突解决方法
    通过以上方法构建的哈希表在理想的情况下能够做到一个关键字对应一个地址,但是实际情况是会有冲突发生,也就是散列函数会将多个关键字映射到同一个地址上。以下是一些解决冲突的方法:
  1)开放地址法:
    ①线性探测法:当发生冲突时,就顺序查看下一个存储位置,如果位置为空闲状态,就将该关键字存储在该位置上,如果还是发生冲突,就依次往后查看,当查看到存储空间的末尾时还是找不到空位置,就返回从头开始查看;

    ②平方探测法:不同于前面线性探测法依次顺序查看下一个位置是否能存储元素,平方探测的规则是以12,−12,22,−22,...,1^2, -1^2, 2^2, -2^2,...,12,−12,22,−22,...,探测新的存储位置能否存储元素;
    ③再散列法:利用两个散列函数,当通过第一个散列函数得到关键字的存储地址发生冲突时,再利用第二个散列函数计算出地址增量,地址计算方式如下:
Hi=(Hash1(key)+i∗Hash2(key))%pH_i = (Hash_1(key)+i*Hash_2(key))\%pHi​=(Hash1​(key)+i∗Hash2​(key))%p
    ④伪随机数法: 当发生地址冲突时,加入一个随机数作为地址增量寻找新的存储地址,地址计算方式如下:
Hi=(Hash(key)+di)%p,其中di为随机数H_i = (Hash(key)+d_i)\%p, \;其中d_i为随机数Hi​=(Hash(key)+di​)%p,其中di​为随机数
  2)拉链法
    将具有相同存储地址的关键字链成一单链表, m个存储地址就设m个单链表,然后用一个数组将m个单链表的表头指针存储起来,形成一个动态的结构,假设散列函数为 Hash(key) = key %13,其拉链存储结构为:

2. 如何使用STL库中的哈希表

(1)导入头文件
  #include<unordered_map>
(2)哈希表的声明和初始化
    1)声明

unordered_map<elemType_1, elemType_2> var_name; //声明一个没有任何元素的哈希表,
//其中elemType_1和elemType_2是模板允许定义的类型,如要定义一个键值对都为Int的哈希表:
unordered_map<int, int> map;

    2)初始化
    以上在声明哈希表的时候并没有给unordered_map传递任何参数,因此调用的是unordered_map的默认构造函数,生成一个空容器。初始化主要有一下几种方式:
     a)在定义哈希表的时候通过初始化列表中的元素初始化:

unordered_map<int, int> hmap{ {1,10},{2,12},{3,13} };
//如果知道要创建的哈希表的元素个数时,也可以在初始化列表中指定元素个数
unordered_map<int, int> hmap{ {{1,10},{2,12},{3,13}},3 };

     b)通过下标运算来添加元素:

//当我们想向哈希表中添加元素时也可以直接通过下标运算符添加元素,格式为: mapName[key]=value;
//如:hmap[4] = 14;
//但是这样的添加元素的方式会产生覆盖的问题,也就是当hmap中key为4的存储位置有值时,
//再用hmap[4]=value添加元素,会将原哈希表中key为4存储的元素覆盖
hmap[4] = 14;
hmap[5] = 15;
cout << hmap[4];  //结果为15

     c)通过insert()函数来添加元素:

//通过insert()函数来添加元素的结果和通过下标来添加元素的结果一样,不同的是insert()可以避免覆盖问题,
//insert()函数在同一个key中插入两次,第二次插入会失败
hmap.insert({ 5,15 });
hmap.insert({ 5,16 });
cout << hmap[5];  //结果为15

     d)复制构造,通过其他已初始化的哈希表来初始新的表:

unordered_map<int, int> hmap{ {1,10},{2,12},{3,13} };
unordered_map<int, int> hmap1(hmap);

3. STL中哈希表的常用函数

(1) begin( )函数:该函数返回一个指向哈希表开始位置的迭代器

unordered_map<int, int>::iterator iter = hmap.begin(); //申请迭代器,并初始化为哈希表的起始位置
cout << iter->first << ":" << iter->second;

(2) end( )函数:作用于begin函数相同,返回一个指向哈希表结尾位置的下一个元素的迭代器

unordered_map<int, int>::iterator iter = hmap.end();

(3) cbegin() 和 cend():这两个函数的功能和begin()与end()的功能相同,唯一的区别是cbegin()和cend()是面向不可变的哈希表

const unordered_map<int, int> hmap{ {1,10},{2,12},{3,13} };
unordered_map<int, int>::const_iterator iter_b = hmap.cbegin(); //注意这里的迭代器也要是不可变的const_iterator迭代器
unordered_map<int, int>::const_iterator iter_e = hmap.cend();

(4) empty()函数:判断哈希表是否为空,空则返回true,非空返回false

bool isEmpty = hmap.empty();

(5) size()函数:返回哈希表的大小

int size = hmap.size();

(6) erase()函数: 删除某个位置的元素,或者删除某个位置开始到某个位置结束这一范围内的元素, 或者传入key值删除键值对

unordered_map<int, int> hmap{ {1,10},{2,12},{3,13} };
unordered_map<int, int>::iterator iter_begin = hmap.begin();
unordered_map<int, int>::iterator iter_end = hmap.end();
hmap.erase(iter_begin);  //删除开始位置的元素
hmap.erase(iter_begin, iter_end); //删除开始位置和结束位置之间的元素
hmap.erase(3); //删除key==3的键值对

(7) at()函数:根据key查找哈希表中的元素

unordered_map<int, int> hmap{ {1,10},{2,12},{3,13} };
int elem = hmap.at(3);

(8) clear()函数:清空哈希表中的元素

hmap.clear()

(9) find()函数:以key作为参数寻找哈希表中的元素,如果哈希表中存在该key值则返回该位置上的迭代器,否则返回哈希表最后一个元素下一位置上的迭代器

unordered_map<int, int> hmap{ {1,10},{2,12},{3,13} };
unordered_map<int, int>::iterator iter;
iter = hmap.find(2); //返回key==2的迭代器,可以通过iter->second访问该key对应的元素
if(iter != hmap.end())  cout << iter->second;

(10) bucket()函数:以key寻找哈希表中该元素的储存的bucket编号(unordered_map的源码是基于拉链式的哈希表,所以是通过一个个bucket存储元素)

int pos = hmap.bucket(key);

(11) bucket_count()函数:该函数返回哈希表中存在的存储桶总数(一个存储桶可以用来存放多个元素,也可以不存放元素,并且bucket的个数大于等于元素个数)

int count = hmap.bucket_count();

(12) count()函数: 统计某个key值对应的元素个数, 因为unordered_map不允许重复元素,所以返回值为0或1

int count = hmap.count(key);

(13) 哈希表的遍历: 通过迭代器遍历

unordered_map<int, int> hmap{ {1,10},{2,12},{3,13} };
unordered_map<int, int>::iterator iter = hmap.begin();
for( ; iter != hmap.end(); iter++){cout << "key: " <<  iter->first  << "value: " <<  iter->second <<endl;
}

一文看懂哈希表并学会使用C++ STL 中的哈希表相关推荐

  1. ​【Python基础】一文看懂 Pandas 中的透视表

    作者:来源于读者投稿 出品:Python数据之道 一文看懂 Pandas 中的透视表 透视表在一种功能很强大的图表,用户可以从中读取到很多的信息.利用excel可以生成简单的透视表.本文中讲解的是如何 ...

  2. mysql删除分表键_一文看懂 MySQL 分区和分表,提高表增删改查效率

    原标题:一文看懂 MySQL 分区和分表,提高表增删改查效率 作者:冯帅,精通Oracle. MySQL. 擅长异构数据库数据同步及迁移.数据库的设计和调优,对高可用方案有深入研究. MySQL分区和 ...

  3. SAP FICO 一文看懂财务三张表

    点击进入:一文看懂财务三张表 更多内容关注公众号:SAPtechnical

  4. 【一文看懂】深度神经网络加速和压缩新进展年度报告

    郑板桥在<赠君谋父子>一诗中曾写道, "删繁就简三秋树,领异标新二月花." 这句诗讲的是,在画作最易流于枝蔓的兰竹时,要去掉其繁杂使之趋于简明如"三秋之树&q ...

  5. 一文看懂:互联网产品分析,该如何做?

    总有同学们在抱怨:"说的是做产品分析,可实际上每天都在埋点,建表,写SQL,对口径,找bug,我分析啥了?到底啥是产品分析?"今天简单分享一下. 所谓产品分析,特指对互联网产品:A ...

  6. 用户画像标签维度_一文看懂用户画像标签体系(包括维度、应用场景)

    一文看懂用户画像标签体系(包括维度.应用场景) 互联网相关企业在建立用户画像时一般除了基于用户维度(userid)建立一套用户标签体系外,还会基于用户使用设备维度(cookieid)建立相应的标签体系 ...

  7. 一文看懂开源许可证丨开源知识科普

    一文看懂开源许可证丨开源知识科普 1. 一文看懂开源许可证丨开源知识科普 1.1. 什么是开源许可证? ("Open Source License") 1.2. 常见开源许可证 1 ...

  8. 一文看懂推荐系统:物品冷启05:流量调控

    一文看懂推荐系统:物品冷启05:流量调控 提示:最近系统性地学习推荐系统的课程.我们以小红书的场景为例,讲工业界的推荐系统. 我只讲工业界实际有用的技术.说实话,工业界的技术远远领先学术界,在公开渠道 ...

  9. 一文看懂-ElasticSearch全文搜索引擎

    一文看懂-ElasticSearch全文搜索引擎 一.ElasticSearch简介 1.1 什么是ElasticSearch ElasticSearch简称ES,其中Elastic 从名字里我们可以 ...

最新文章

  1. java代码。继承。。。很戳我的心啊。。不太懂。super的真正用法
  2. 安卓GreenDao框架一些进阶用法整理(转)
  3. Boost:双图bimap与range范围的测试程序
  4. VTK:绘图之Diagram
  5. c语言程序优化设计,C程序设计语言的教学策略优化设计
  6. Manacher's algorithm: 最长回文子串算法
  7. 8.5 传输介质和网络应用
  8. 浅谈Netty中ServerBootstrap服务端源码(含bind全流程)
  9. HTML5 高频面试题!!!
  10. Asp.net Web Api开发Help Page配置和扩展
  11. office2010所做更改会影响共用模板normal
  12. 和面试官对线HashMap
  13. 【C++】「一本通 1.1 例 4」加工生产调度
  14. 工作小笔记——使用Cartographer建图和调优
  15. SM2262EN+东芝BICS3 1TB开卡报错处理
  16. 文件系统专栏 | 之文件系统架构
  17. vivox21支持html,【vivoX21评测】看完vivo X21这20个重点,我忍不住剁手_vivo X21_手机评测-中关村在线...
  18. 环境监测调查无人船OES120
  19. Option 82在校园网的应用与实现(转)
  20. BAT产品经理面试题--如何同时拿下百度腾讯阿里的产品岗offer

热门文章

  1. 网站建设费用要多少?这些内容要了解
  2. Discuz论坛修改
  3. HTC G17刷Recovery、刷机详细教程
  4. AttributeSet自定义控件
  5. PLSQL ROWCOUNT
  6. 帮我写一篇外骨骼文献综述
  7. 从产品销量考虑渠道布局——洗衣机行业数据分析
  8. 数据结构与算法分析之---部分排序算法的实现
  9. 【大话数据结构】——-数据结构
  10. 【钉钉】通过自定义机器人向钉钉群发送消息