Learning C++ No.25【开散列封装unordered_set和unordered_map】

这篇具有很好参考价值的文章主要介绍了Learning C++ No.25【开散列封装unordered_set和unordered_map】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

引言:

北京时间:2023/5/29/7:05,上星期更文一篇,且该篇博客在周三就写完了,所以充分体现,咱这个星期摆烂充分,哈哈哈!现在的内心情感没有以前那么从容了,这次摆的时间是有点久了,但本质影响不大,因为我现在还在码字,三天不学习,或者说是没有踏实学习,目前给我的感觉很难受,就像是好久好久没有学习过一样,感觉三天前学的东西,已经忘的差不多了,但,不慌,因为我们有写博客进行总结,可以让我们第一时间将相关知识回顾,所以这也是写博客最大的好处之一,并且在这三天的摆烂中,不是连续性的,而是间断性,可能这个间断性,也是我摆烂的重要原因之一,并且摆烂的过程还是那么朴实无华,王者荣耀,快4个月没玩,一开始玩的不怎样,后来手感越来越好,逐渐疯狂,一路连胜,把把c,这也可能就是为什么能持续摆烂的原因吧!So,简简单单,由于我们上篇博客的内容是哈希表的自我封装,所以该篇博客的内容就是unordered_set和unordered_map的封装 ,希望这不是我周末摆烂的开始,并且摆烂可以,但是一定需要在有一定的学习内容之后,充分反省,希望以后看到该篇博客的引言时,不是以今天这种较为落寞的情绪吧!

Learning C++ No.25【开散列封装unordered_set和unordered_map】

STL中有关unordered_set和unordered_map的知识

在上篇博客中,我们自己封装实现了哈希表,明白了许多有关哈希表的知识,如:哈希函数,哈希地址,哈希下标,哈希值等!那么哈希表有什么用呢?当我们谈到哈希表的用处之时,最好的回答方向就是从哈希表的优势出发,哈希表在查找和访问数据方面具有超高的效率(O(1)),就算是红黑树在查找方面也是远远不如,当然,不同的场景,红黑树和哈希表都各具风骚,否则肯定是一山不容二虎,其中一个早就被淘汰了,其中从之前我们使用红黑树封装set和map的博客中也能看出,红黑树在生活中的许多领域都应用广泛,所以人们特地的将红黑树进行了一定的封装,也就是set和map,同理,哈希表也被人们广泛使用,也被封装成了STL中的某种数据结构(关联式容器),也就是该篇博客的重点内容,unordered_set和unordered_map,所以接下来就让我们一起看看unordered_set和unordered_map的具体使用方法和自我封装吧!如下:

unordered_set和unordered_map的具体使用方法

unordered_set使用方法

unordered_set使用文档
通过文档我们可以看出,unordered_set和我们之前学习的set的使用方式是相同的,本质没有什么区别,所以这里我们不多做分析,具体直接看如下代码:
Learning C++ No.25【开散列封装unordered_set和unordered_map】
简简单单,同理就是插入、查找、删除这些基础接口和迭代器的使用,唯一值得注意的是:此时使用哈希表实现的unordered_set它不同于红黑树实现的set,一个是有序的,一个是无序的,当然,红黑树肯定是中序遍历有序的那一个,哈希表无序,且set是一个双向迭代器,而unordered_set是一个单向迭代器,具体为什么unordered_set设计成单向迭代器,而不设计成双向迭代器,原因如下:

  1. 对应数据在插入和删除的时候,可能会改变原哈希表中相关数据的链接关系,所以很难确保双向迭代器始终能够访问到对应的数据
  2. 因为哈希表中的数据是通过哈希地址控制,且哈希地址是通过哈希函数和对应的哈希值得到,所以哈希表中的数据都是随机无序存储,具有不可预测的性质
  3. 在哈希表结构中(开散列),数据之间是通过链式结构连接在一起的,所以我们可以直接通过对应的哈希地址去访问到对应的链表,再直接遍历链表,找到目标元素,而不需要按照固定的顺序去遍历整个哈希表,效率更高

unordered_map使用方法

unordered_map使用文档
多的不说,少的不唠,同理map使用方法,直接看代码,如下:
Learning C++ No.25【开散列封装unordered_set和unordered_map】
使用方法,同理map相关知识,且具体注意事项,在上述unordered_set已经强调,多了也没有,唯一值得注意的是和unordered_set最大的区别,也就是方括号运算符的使用,当然在map中方括号的实现和使用我们已经详细讲解过了,这里就不多加描述,接下来直接进入unordered_set和unordered_map的封装,如下代码所示:

unordered_set和unordered_map的封装

1.解决不同模型问题
第一点,同理红黑树实现set和map,还是数据类型问题,unordered_set和unordered_map也具有该方面的问题,如何使用同一份哈希表的代码同时实现unordered_set和unordered_map,类比红黑树实现set和map,这里依然使用泛型编程,当然也就是模板来解决该问题,基本原理就是将哈希表的哈希结点设计成一个模板类型,不管是unordered_set还是unordered_map,只要想要调用哈希表就需要把对应类型的模板参数传过来,所以这样我们就可以很好的解决Key模型和Key/Value模型使用同一份哈希代码的问题,具体代码如下:
Learning C++ No.25【开散列封装unordered_set和unordered_map】
如上图所示,总的来说,就是在使用unordered_set和unordered_map这两个模板类的时候,这两个模板类会去调用哈希表构造出一个对象,使用该对象去调用哈希表中的公共成员函数,并且此时传模板参数的时候,unordered_set传的是Key键,而unordered_map 传的是键值对pair结构体,并且注意:该pair结构中的数据也是模板类型,最后将模板参数传递给哈希表之后,哈希表在实例化的过程中,就会将对应的哈希结点给示例化成对应的数据类型,也就是你传Key,那么哈希结点就是Key类型,你传键值对,那么哈希结点就是键值对类型,这就是泛型编程的一大优点

2.解决泛型编程获取Key值问题
搞定了上述有关类型传参问题,此时我们正式开始封装,并且在红黑树中,我们对源码的写法已经有了教深的研究,此时我们就不再去看对应的源码了,因为本质都是换汤不换药,在红黑树封装set和map的博客中,我们已经将有关传模板参数导致不能确定类型的问题给解决了,也就是因为我们传的是模板参数,所以在编写红黑树代码的时候,不能使用具体的类型去访问数据,例:在进行比较大小的时候,unordered_set可以直接使用Key去比较大小,但是unordered_map却不行,因为unordered_map是一个键值对,是一个pair结构体,我们期望比较大小的方法是使用pair结构体中的Key去比较,而不是整个pair结构去比较,所以此时这个问题需要解决,解决的方法就是在unordered_set和unordered_map中构造一个内部类,该类实现一个仿函数,用于返回对应不同模型的Key值,最后再将该内部类作为一个模板参数传递到哈希表中,供给哈希表使用,哈希表再根据该模板参数取构造一个对象,使用该对象去调用对应的仿函数,最终利用仿函数获取到对应模型的Key值,如下代码所示:
Learning C++ No.25【开散列封装unordered_set和unordered_map】
如上图所示,通过上述文字和图示,应该可以很好的搞定该块知识点,本质就是想要获取到键值对pair结构体中的Key值而已,多了的没有,谁让我们想让unordered_set和unordered_map在一个桌子上吃饭呢?

3.解决存储数据类型的问题
OK,这个问题肯定是该篇博客的一个新知识点,虽然我们在哈希表实现的时候,已经详细的讲解过了,但是对于红黑树实现set和map来说,这个知识点是哈希表特有的,所以在此应该是属于新鲜货,值得我们重点讲解,同理哈希表中讲的,哈希表不是为了单单存储整形数据,而是希望可以存储任何类型的数据,无论是字符串类型还是自定义类型,所以为了解决这个问题,那么在进行哈希编码的时候,也就是使用哈希值进行哈希运算计算对应哈希地址的时候,我们需要将每种类型的数据都映射成一个整形数据,因为只有整形数据才可以符合哈希运算要求,但同理我们的数据类型使用的是模板类型,所以想要获取到这个数据类型映射出来的整形值,肯定不能在哈希表中获得,当然也不是在unordered_set或者unordered_map中获得,而是在我们调用unordered_set或者unordered_map进行传参时,通过一定的哈希函数实现获得,从而间接通过unordered_set和unordered_map
将该模板参数传递给哈希表,并且供给哈希表使用,让哈希表可以完成各种类型的哈希运算,从而在相应的哈希地址上存储各种类型的数据,如下图所示:
Learning C++ No.25【开散列封装unordered_set和unordered_map】

正式进入unordered_set和unordered_map的封装

搞定了上述有关泛型编程的知识,此时我们正式进入unordered_set和unordered_map的封装,本质没有什么太新奇的知识点,大致和set、map那块是类似的,也就是基础接口的封装和普通迭代器、const迭代器这些知识,并且基础接口的实现,就是去调用哈希表中对应的接口而已,所以不需要我们多讲,我们同样是把重点放在迭代器上,主要还是因为unordered_set的普通迭代器和const迭代器都是const迭代器,所以这块知识比较细化,需要我们琢磨一下

哈希表中迭代器相关知识

上篇博客,自我封装哈希表中,我们只实现了相关基础接口,并没有实现迭代器,所以因为此时unordered_set和unordered_map需要使用迭代器,此时我们就需要把哈希表的迭代器给实现,具体如下代码所示:
Learning C++ No.25【开散列封装unordered_set和unordered_map】
搞定了哈希表中有关迭代器的知识,此时我们就可以正式进入 unordered_set和 unordered_map的封装啦!如下:

unordered_set的封装

唯一值得注意的是,unordered_set的普通迭代器和const迭代器本质都是const迭代器,所以在实现迭代器时,一定需要格外小心,非常容易因为const导致出错,具体代码如下所示:
Learning C++ No.25【开散列封装unordered_set和unordered_map】

unordered_map的封装

同理,但不同的是此时unordered_map的普通迭代器就是普通迭代器,所以没什么需要特别注意的地方,如果有的话,那么就是键值对pair结构体中的Key值,我们要给成const类型,因为Key值坚决不允许被修改的,具体代码如下:
Learning C++ No.25【开散列封装unordered_set和unordered_map】文章来源地址https://www.toymoban.com/news/detail-465398.html

总结:哈希代码有关方面的知识,我们搞定的就差不多了,接下来只要认识一下哈希表在位图方面的应用,哈希表有关的知识我们就搞定啦!

到了这里,关于Learning C++ No.25【开散列封装unordered_set和unordered_map】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C++】unordered_set 和 unordered_map 使用 | 封装

    unordered_map官方文档 unordered_set 官方文档 set / map与unordered_set / unordered_map 使用功能基本相同,但是两者的底层结构不同 set/map底层是红黑树 unordered_map/unordered_set 底层是 哈希表 红黑树是一种搜索二叉树,搜索二叉树又称为排序二叉树,所以 迭代器遍历是有序的 而哈希表对应的

    2024年02月06日
    浏览(48)
  • 【C++】哈希表封装实现 unordered_map 和 unordered_set

    在 C++98 中,STL 提供了底层为红黑树结构的一系列关联式容器,在查询时效率可达到 O(logN),即最差情况下只需要比较红黑树的高度次;但是当树中的节点非常多时,其查询效率也不够极致。 最好的查询是,不进行比较或只进行常数次比较就能够将元素找到,因此在 C++11 中,

    2023年04月16日
    浏览(49)
  • 【C++】STL——用一个哈希表封装出unordered_map和unordered_set

    根据先前对unordered_map和unordered_set的学习,我们得知其底层是借助哈希表来实现的,接下来我们会使用上篇博客实现的开散列哈希表来模拟实现unordered_map和unordered_set,哈希表源代码链接: Hash/Hash/HashBucket.h · wei/cplusplus - 码云 - 开源中国 (gitee.com) 下面我们对哈希表进行改造,

    2023年04月18日
    浏览(47)
  • 【C++】如何用一个哈希表同时封装出unordered_set与unordered_map

    👀 樊梓慕: 个人主页  🎥 个人专栏: 《C语言》 《数据结构》 《蓝桥杯试题》 《LeetCode刷题笔记》 《实训项目》 《C++》 《Linux》 《算法》 🌝 每一个不曾起舞的日子,都是对生命的辜负 目录 前言 1.哈希桶源码  2.哈希表模板参数的控制 3.字符串作为键值如何映射哈希值

    2024年03月26日
    浏览(51)
  • 由[哈希/散列]模拟实现[unordered_map/unordered_set] (手撕迭代器)

    以下两篇文章均为笔者的呕心沥血 想要搞懂本篇文章的uu请自行查阅 哈希/散列的细节实现 哈希/散列–哈希表[思想到结构][==修订版==] 手撕迭代器的细节处理 模拟实现map/set[改编红黑树实现map/set容器底层]

    2024年02月07日
    浏览(45)
  • 【C++学习】哈希表的底层实现及其在unordered_set与unordered_map中的封装

    🎉个人名片: 🐼作者简介:一名乐于分享在学习道路上收获的大二在校生 🙈个人主页🎉:GOTXX 🐼个人WeChat:ILXOXVJE 🐼本文由GOTXX原创,首发CSDN🎉🎉🎉 🐵系列专栏:零基础学习C语言----- 数据结构的学习之路----C++的学习之路 🐓每日一句:如果没有特别幸运,那就请特

    2024年04月16日
    浏览(47)
  • Learning C++ No.24 【哈希/散列实战】

    北京时间:2023/5/20/7:30,周六,可惜有课,而且还是早八,说明我们现在没有多少的学习时间啦!得抓紧把该博客的引言给写完,我们距离期末考越来越近啦!再过一个星期就要开始停课,然后进行什么实训,目前推测,这个实训估计就是在摆烂中摆烂,不过没有关系,只要

    2024年02月06日
    浏览(44)
  • 封装unordered_set&&unordered_map

    注:实现unordered系列容器是为了学习,因此并非将全部接口实现,所以只实现部分接口 目录 哈希表的改造 模板参数列表的改造 增加迭代器操作 增加通过T获取value操作 HashTable.h的修改 unordered_set的封装 unordered_map的封装 K:关键码类型 T:不同容器T的类型不同,如果是unorder

    2024年02月05日
    浏览(40)
  • 【unordered_map和unordered_set的封装】

    这里的思路与前面讲解map/set的封装思路一致,STL不喜欢直接实例化出两份几乎相同的代码,所以用了模板参数来处理,还是老规矩: set中传入的是K,K,map中传入的是K,PairK,V .这样我们在哈希桶的结构中只需要用一个T类型的模板参数接受上层传入的参数即可。 基本框架的改造:

    2024年02月08日
    浏览(36)
  • 【C++】哈希表:开散列和闭散列

    📝 个人主页 :超人不会飞) 📑 本文收录专栏 :《C++的修行之路》 💭 如果本文对您有帮助,不妨 点赞、收藏、关注 支持博主,我们一起进步,共同成长! 在前面的文章中,我们学习了红黑树,其查找数据的效率很高,查找的次数最差是树的高度logN次,并且要进行多次比

    2023年04月27日
    浏览(82)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包