【C++历练之路】unordered_map与unordered_set的封装实现

W...Y的主页 😊

代码仓库分享💕 

 


前言:我们已经认识并实现了哈希底层的逻辑,创建出了其开散列。现在我们要进行封装,类比STL中的unordered_set 与 unordered_map。

目录

1. 模拟实现

1.1 哈希表的改造

1.2 unordered_set 与 unordered_map的封装


1. 模拟实现

1.1 哈希表的改造

1. 模板参数列表的改造

unordered_set 与 unordered_map的泛型与map与set的泛型有些类似,unordered_set 与 unordered_map比map与set多一个仿函数,他们都取key值,并且需要一个hash值作为映射点。所以需要两个仿函数。

K:关键码类型
V: 不同容器V的类型不同,如果是unordered_map,V代表一个键值对,如果是
unordered_set,V 为 K
KeyOfValue: 因为V的类型不同,通过value取key的方式就不同,我们必须使用一个仿函数进行才能实现unordered_map/set。
Hash: 哈希函数仿函数对象类型,哈希函数使用除留余数法,需要将Key转换为整形数字才能
取模

template<class K, class V, class KeyOfValue, class Hash = DefHashF<T> >
class HashBucket;

只有我们调用unordered_set 与 unordered_map时,编译器会识别关键字进行操作,所以我们定义的仿函数可以使用类部类中:

//unodered_set
template<class K, class Hash = HashFunc<K>>
class unordered_set
{struct SetKeyOfT{const K& operator()(const K& key){return key;}};
public:typedef typename hash_bucket::HashTable<K, const K, SetKeyOfT, Hash>::iterator iterator;
};//unorder_map
template<class K, class V, class Hash = HashFunc<K>>
class unordered_map
{struct MapKeyOfT{const K& operator()(const pair<K, V>& kv){return kv.first;}};public:typedef typename hash_bucket::HashTable<K, pair<const K, V>, MapKeyOfT, Hash>::iterator iterator;
};

 

所以我们HashNode中的泛型应该修改:

template<class T>
struct HashNode
{HashNode<T>* _next;T _data;HashNode(const T& data):_next(nullptr), _data(data){}
};

2. 增加迭代器操作

我们要实现迭代器的++、*、!=等等,因为HashNode中为单链表,所以我们不需要实现--操作。

那我们应该如何实现呢?

 上图是散列表结构,迭代器的底层就是指针,所以我们就要使用指针指向桶中的元素。所以我们就要HashNode的指针与HashTable的指针作为迭代器成员。

struct __HTIterator
{typedef HashNode<T> Node;typedef HashTable<K, T, KeyOfT, Hash> HT;typedef __HTIterator<K, T, KeyOfT, Hash> Self;Node* _node;HT* _ht;__HTIterator(Node* node, HT* ht):_node(node), _ht(ht){}
};

begin()与end()函数非常简单,begin就找vector中第一个不为空的指针,返回其值即可。

iterator begin()
{for (size_t i = 0; i < _tables.size(); i++){// 找到第一个桶的第一个节点if (_tables[i]){return iterator(_tables[i], this);}}return end();
}

end就是返回空即可:

iterator end()
{return iterator(nullptr, this);
}

++其实是最难实现的,因为当给予一个指针时,我们要桶的下一个节点,如果这个桶的所以节点全部走完就要寻找下一个不为空的桶即可。

Self& operator++()
{if (_node->_next){// 当前桶还是节点_node = _node->_next;}else{// 当前桶走完了,找下一个桶KeyOfT kot;Hash hs;size_t hashi = hs(kot(_node->_data)) % _ht->_tables.size();// 找下一个桶hashi++;while (hashi < _ht->_tables.size()){if (_ht->_tables[hashi]){_node = _ht->_tables[hashi];break;}hashi++;}// 后面没有桶了if (hashi == _ht->_tables.size()){_node = nullptr;}}return *this;
}

 迭代器中剩余函数:

bool operator!=(const Self& s)
{return _node != s._node;
}T& operator*()
{return _node->_data;
}

1.2 unordered_set 与 unordered_map的封装

//unordered_set
namespace why
{template<class K, class Hash = HashFunc<K>>class unordered_set{struct SetKeyOfT{const K& operator()(const K& key){return key;}};public:typedef typename hash_bucket::HashTable<K, const K, SetKeyOfT, Hash>::iterator iterator;iterator begin(){return _ht.begin();}iterator end(){return _ht.end();}bool insert(const K& key){return _ht.Insert(key);}private:hash_bucket::HashTable<K, const K, SetKeyOfT, Hash> _ht;};

 

//unordered_map
namespace why
{template<class K, class V, class Hash = HashFunc<K>>class unordered_map{struct MapKeyOfT{const K& operator()(const pair<K, V>& kv){return kv.first;}};public:typedef typename hash_bucket::HashTable<K, pair<const K, V>, MapKeyOfT, Hash>::iterator iterator;iterator begin(){return _ht.begin();}iterator end(){return _ht.end();}bool insert(const pair<K, V>& kv){return _ht.Insert(kv);}private:hash_bucket::HashTable<K, pair<const K, V>, MapKeyOfT, Hash> _ht;};

以上就是unordered_set 与 unordered_map的封装的全部内容,具体代码在我的gitee代码库中,想要的可以自行去取!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1420401.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

LabVIEW天然气压缩因子软件设计

LabVIEW天然气压缩因子软件设计 项目背景 天然气作为一种重要的能源&#xff0c;其压缩因子的准确计算对于流量的计量和输送过程的优化具有关键意义。传统的计算方法不仅步骤繁琐&#xff0c;而且难以满足现场快速响应的需求。因此&#xff0c;开发一款既能保证计算精度又便于…

PROTEUS仿真软件的使用及存储器的设计

proteus proteus&#xff0c;即EDA工具软件。Proteus软件是英国Lab Center Electronics公司出版的EDA工具软件。它不仅具有其它EDA工具软件的仿真功能&#xff0c;还能仿真单片机及外围器件。它是比较好的仿真单片机及外围器件的工具。虽然国内推广刚起步&#xff0c;但已受到…

四十九坊股权设计,白酒新零售分红制度,新零售策划机构

肆拾玖坊商业模式 | 白酒新零售体系 | 新零售系统开发 坐标&#xff1a;厦门&#xff0c;我是易创客肖琳 深耕社交新零售行业10年&#xff0c;主要提供新零售系统工具及顶层商业模式设计、全案策划运营陪跑等。 不花钱开3000多家门店&#xff0c;只靠49个男人用一套方法卖白酒…

ADOP带你了解:可堆叠交换机:为什么和为什么不

在快速发展的网络环境中&#xff0c;企业需要高效、精简的管理解决方案&#xff0c;以在竞争中保持领先地位。交换机堆叠已成为一种强大的技术&#xff0c;它不仅可以简化网络管理&#xff0c;还可以提高整体效率。在本文中&#xff0c;我们将探讨可堆叠交换机和交换机堆叠的概…

【CMU 15-445】Proj4 Concurrency Control

Concurrency Control 通关记录Task1 TimestampsTask2 Storage Format and Sequential ScanTask3 MVCC ExecutorsTask3.1 Insert ExecutorTask3.2 CommitTask3.3 Update and Delete ExecutorTask3.4 Stop-the-world Garbage Collection Task4 Primary Key IndexTask4.0 Index Sc…

day05-面向对象内存原理和数组

day05 面向对象内存原理和数组 我们在之前已经学习过创建对象了,那么在底层中他是如何运行的。 1.对象内存图 1.1 Java 内存分配 Java 程序在运行时&#xff0c;需要在内存中分配空间。为了提高运算效率&#xff0c;就对空间进行了不同区域的划分&#xff0c;因为每一片区域…

音视频-H264编码封装- MP4格式转Annex B格式

目录 1&#xff1a;H264语法结构回顾 2&#xff1a;H264编码补充介绍 3&#xff1a;MP4模式转Annex B模式输出到文件示例 1&#xff1a;H264语法结构回顾 在之前文章里介绍过H264的语法结构。 传送门: 视音频-H264 编码NALU语法结构简介 2&#xff1a;H264编码补充介绍 H…

前端笔记-day02

文章目录 01-无序列表02-有序列表03-定义列表04-表格06-表格-合并单元格07-表单-input08-表单-input占位文本09-表单-单选框10-表单-上传多个文件11-表单-多选框12-表单-下拉菜单13-表单-文本域14-表单-label标签15-表单-按钮16-无语义-span和div17-字体实体19-注册登录页面 01…

[240512] x-cmd 发布 v0.3.6: (se,wkp,ddgo...)x( kimi,gemini,gpt...)

目录 x-cmd 发布 v0.3.6新增了 jina 模块新增了 ddgo 模块新增了 se 模块wkp 模块新增了 writer 模块cosmo 模块 x-cmd 发布 v0.3.6 本次版本的最新引入的功能都是目的为了进一步探索 LLM 的使用。 本版本的改进分为两类&#xff1a;资讯类模块&#xff08;Wikipedia&#xf…

十三、Redis哨兵模式--Sentinel

上一篇介绍了Redis中的主从复制。我们知道Redis主从中一般只有主节点对外提供写操作&#xff0c;如果主节点发生故障&#xff0c;为了保证Redis的可用性&#xff0c;这时就要在可用的slave节点中&#xff0c;挑选一个作为主节点。这种切换操作如果是人为的操作&#xff0c;那么…

39-5 入侵检测系统(IDS)- 安装配置IDS(第三天安装成功)

官网:Snort Rules and IDS Software Download 参考: (这位大佬分享了安装包下载链接):https://www.cnblogs.com/taoyuanming/p/12722263.html (安装过程参考这位大佬):Snort 安装与配置(CentOS 7)_centos 7 snort-CSDN博客一、安装 IDS(我这里在 CentOS 7 虚拟机中安…

【Docker】Ubunru下Docker的基本使用方法与常用命令总结

【Docker】docker的基本使用方法 镜像image与容器container的关系基本命令- 查看 Docker 版本- 拉取镜像- 查看系统中的镜像- 删除某个镜像- 列出当前 Docker 主机上的所有容器&#xff0c;包括正在运行的、暂停的、已停止的&#xff0c;以及未运行的容器- 列出当前 Docker 主机…

【强训笔记】day19

NO.1 代码实现&#xff1a; #include <iostream> using namespace std;int gcd(int x,int y) {if(y0) return x;return gcd(y,x%y); } int main() {int n,a;while(cin>>n>>a){int b;for(int i0;i<n;i){cin>>b;if(a>b) ab;else agcd(a,b);}cou…

验证码生成--kaptcha

验证码生成与点击重新获取验证码 如图所示&#xff0c;本文档仅展示了验证码的生成和刷新显示。 1. 概述 系统通过生成随机验证码图像和文本。 2. 代码分析 2.1. Maven依赖 <dependency><groupId>com.github.penggle</groupId><artifactId>kaptch…

RustDesk 自建服务器部署和使用教程

RustDesk 是一个强大的开源远程桌面软件&#xff0c;是中国开发者的作品&#xff0c;它使用 Rust 编程语言构建&#xff0c;提供安全、高效、跨平台的远程访问体验。可以说是目前全球最火的开源远程桌面软件了&#xff0c;GitHub 星星数量达到了惊人的 64k&#xff01; 与 Team…

如何看待云计算的第三次浪潮?

如何看待云计算的第三次浪潮&#xff1f; 来自云栖大会的演讲你如何看待云计算的第三次浪潮&#xff1f;云计算的第三次浪潮将会给社会带来怎样的变革&#xff1f;开发者在云计算的第三次浪潮中将会有哪些机遇和挑战&#xff1f;机遇挑战 来自云栖大会的演讲 在2023云栖大会上…

SpringSecurity安全过滤器工作原理

前面通过三篇文章&#xff0c;从底层代码的角度分析了SpringSecurity的初始化过程。 接下来我们就要具体看一下&#xff0c;Spring Security的安全过滤器初始化、装配好之后&#xff0c;到底是怎么工作的。 还是按图索骥 下面我们简单从底层源码分析一下&#xff0c;请求是怎…

【全开源】Fastflow工作流系统(源码搭建/上线/运营/售后/维护更新)

一款基于FastAdminThinkPHP开发的可视化工作流程审批插件&#xff0c;帮助用户基于企业业务模式和管理模式自行定义所需的各种流程应用&#xff0c;快速构建企业自身的流程管控体系&#xff0c;快速融合至企业协同OA办公系统。 提供全部无加密服务端源码和前端源代码&#xff0…

树莓派4B-搭建一个本地车牌识别服务器

实现目标&#xff1a; 一、设备自启后能够获得服务的ip与端口号&#xff0c;用于计算机连接设备&#xff1b; 二、计算机可以通过服务ip与端口访问设备服务&#xff1b; 三、上传需要处理的数据&#xff0c;返回结果反馈给用户&#xff1b; 四、上传到服务器的数据不会导致设备…

亲测-wordpress文章实时同步发布修改删除多个站点的WP2WP插件

一款将wordpress文章同步到其他WordPress网站的插件&#xff0c;通过这款插件&#xff0c;可以保持不同博客之间文章发布、修改、删除的同步。 安装步骤&#xff1a; 主站和分站都要上传这个插件 1.把插件上传到wp-content\plugins解压出来wp2wp文件夹&#xff0c;然后启用插…