news 2026/7/31 0:52:44

C++--哈希封装my_unordered_set和my_unordered_map

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C++--哈希封装my_unordered_set和my_unordered_map

目录

一,引言

二,基本结构

三,hash迭代器

四,HashTable的基本结构


一,引言

在实现哈希表之后,在unordered_set和unordered_map的学习中。了解到这两者的数据结构底层是由哈希表实现的,为此在实现哈希表的基础上对哈希表进行封装。

二,基本结构

首先要需要对Node节点进行修改。此过程和红黑树的封装类似。由上层结构决定是set还是map:
参考代码如下:

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

T的具体类型由上层传入进行决定。


KeyOFT仿函数以及hash仿函数

在上述节点的基本类型中为T类型,因此并不直到上层究竟是map还是set。为此第一个仿函数的作用是返回这两者的key值。

hash仿函数和哈希表的实现中作用一致,这里就不详细讲解。

三,hash迭代器

哈希表表支持的迭代器是单向迭代器,红黑树所支持的是双向迭代器。但是基础机构基本上相似,参考代码如下:

template<class K, class T, class Ptr, class Ref, class KeyOfT, class Hash> struct HTIterator { typedef HashNode<T> Node; typedef HTIterator<K, T, Ptr, Ref, KeyOfT, Hash> Self; Node* _node; const HashTable<K, T, KeyOfT, Hash>* _pht; HTIterator(Node* node, const HashTable<K, T, KeyOfT, Hash>* pht) :_node(node) , _pht(pht) {} };

由于迭代器要实现++操作。哈希表内部是链式结构,在迭代器++的过程中,当该节点所链接的节点结束,则需要寻找下一个数组的节点。为此不仅需要node指针指向节点,还需要哈希表指针指向该哈希表。

在该迭代器的模板的第二,三,四个参数分别代表这数据(数据类型)(数据指针类型)(数据引用类型)。方便后续区分const迭代器。在迭代器内部封装的结构和红黑树相似。

operator*

Ref operator*() { return _node->_data; }

operator->

Ptr operator->() { return &_node->_data; }

operator!=

bool operator!=(const Self& s) { return _node != s._node; }

operator++

Self& operator++() { if (_node->_next) { _node = _node->_next; } else { KeyOfT kot; Hash hs; size_t hashi = hs(kot(_node->_data)) % _pht > _tables.size(); ++hashi; while (hashi < _pht->_tables.size()) { if (_pht->_tables[hashi]) { break; } ++hashi; } if (hashi == _pht->_tables.size()) { _node = nullptr; // end() } else { _node = _pht->_tables[hashi]; } } return *this; }

若该节点的下一个位置还有节点,则直接node++。若已经到这条链的最后一个节点。则重新确定这个节点的位置。找到下一个非空节点。返回这个位置的迭代器。

四,HashTable的基本结构

template<class K, class T, class KeyOfT, class Hash> class HashTable { // 友元声明 template<class K, class T, class Ptr, class Ref, class KeyOfT, class Hash> friend struct HTIterator; typedef HashNode<T> Node; public: typedef HTIterator<K, T, T*, T&, KeyOfT, Hash> Iterator; typedef HTIterator<K, T, const T*, const T&, KeyOfT, Hash> private: vector<Node*> _tables; // size_t _n = 0; // };

这里需要注意类模板的友元声明。使得上文HTIterator能够访问HashTable的私有成员。

下面就是迭代器封装

Iterator Begin() { if (_n == 0) return End(); for (size_t i = 0; i < _tables.size(); i++) { Node* cur = _tables[i]; if (cur) { return Iterator(cur, this); } } return End(); } Iterator End() { return Iterator(nullptr, this); } ConstIterator Begin() const { if (_n == 0) return End(); for (size_t i = 0; i < _tables.size(); i++) { Node* cur = _tables[i]; if (cur) { return ConstIterator(cur, this); } } return End(); } ConstIterator End() const { return ConstIterator(nullptr, this); }

Insert的修改

Insert修改和这个基本上都类似。

五,my_unordered_set封装

基本结构和红黑树相似,与红黑树不同的是这里需要提供上文中所将到的KeyOFT,来返回key的值,参考代码如下:

struct SetKeyOfT { const K& operator()(const K& key) { return key; } };

基本结构如下:

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; typedef typename hash_bucket::HashTable<K, const K, SetKeyOfT, Hash>::ConstIterator const_iterator; private: hash_bucket::HashTable<K, const K, SetKeyOfT, Hash> _ht; };

这里需要注意不能单单用typedef,而是要使用typedef typename来强调后者修饰的是类型,而不是变量。map和set基本上一致。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/29 19:19:28

44、FTP安全指南与服务器配置解析

FTP安全指南与服务器配置解析 1. FTP安全原则 FTP存在多种主要威胁模型,具体如下: - 匿名访问威胁 :匿名用户应仅能列出和下载公共文件,可能允许上传文件到指定的“incoming”目录。绝不能让他们将权限提升至更受信任用户的权限。 - 本地用户账户威胁 :本地用户通过…

作者头像 李华
网站建设 2026/7/30 5:53:36

59、完整的 iptables 启动脚本介绍

完整的 iptables 启动脚本介绍 在网络安全配置中,使用 iptables 配置 netfilter 是常见的操作,它可以在 DMZ 服务器和保护它的防火墙中实现有效的网络过滤。下面将为大家介绍两个完整的 iptables 启动脚本,一个用于堡垒主机,另一个用于多宿主防火墙系统。 1. 堡垒主机(W…

作者头像 李华
网站建设 2026/7/30 22:31:30

NCMconverter:解锁网易云音乐格式限制的终极解决方案

NCMconverter&#xff1a;解锁网易云音乐格式限制的终极解决方案 【免费下载链接】NCMconverter NCMconverter将ncm文件转换为mp3或者flac文件 项目地址: https://gitcode.com/gh_mirrors/nc/NCMconverter 你是否曾经下载了网易云音乐的ncm格式文件&#xff0c;却发现无…

作者头像 李华
网站建设 2026/7/30 22:04:35

知网AIGC查重率100%?6个技巧快速把AI率降低5%!

知网AIGC率过高是当前很多学生和研究者在论文写作中遇到的普遍问题。别慌&#xff0c;只要掌握正确的方法&#xff0c;完全可以将AI生成痕迹有效降低&#xff0c;顺利通过检测。 一、知网AIGC检测原理是什么&#xff1f; 知网等平台通过以下方式判断内容是否由AI生成&#xf…

作者头像 李华
网站建设 2026/7/29 19:56:29

6.React记忆化处理

使用Hook进行记忆化处理 在React中&#xff0c;每次渲染时函数组件都会被调用&#xff0c;这意味着频繁的计算和函数创建可能会对性能产生负面影响。为了优化性能并防止不必要的重新计算&#xff0c;React提供了3种钩子: useMemo()、useCallback()和useRef()。这些钩子分别允许…

作者头像 李华