当前位置: 首页 > news >正文

哈希表封装myunordered_map和myunordered_set

1.set和map框架

//unorderedset.h
namespace smc
{template<class K, class Hash = HashFunc<K>>class unordered_set{struct SetKeyOfT{const K& operator()(const K& key){return key;}};public:bool insert(const K& key){return _ht.Insert(key);}private:hash_bucket::HashTable<K, K, SetKeyOfT, Hash> _ht;};
}
// unorderedMap.h
namespace smc
{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:bool insert(const pair<K, V>& kv){return _ht.Insert(kv);}private:hash_bucket::HashTable<K, pair<K, V>, MapKeyOfT, Hash> _ht;};
}

2.支持iterator的实现

2.1 思路分析

  • 哈希表的迭代器是单向迭代器
  • 难点是operator++的实现。iterator中有一个指向结点的指针,如果当前桶下面还有结点, 则结点的指针指向下一个结点即可。如果当前桶走完了,则需要想办法计算找到下一个桶。
  • 所以迭代器的构造需要一个结点指针+一个哈希表对象指针,方便计算并指向哈希桶一个位置,依次往后找下⼀个不为空的桶即可
  • begin()返回第一个桶中第一个节点指针构造的迭代器,end()返回迭代器可以用空表示
  • unordered_set的iterator也不支持修改,把unordered_set的第二个模板参数改成const K即可,
  • unordered_map的iterator不支持修改key但是可以修改value,我们把unordered_map的第二
  • 个模板参数pair的第一个参数改成const K即可
    //HashTable.h
    template<class T>
    struct HashNode
    {T _data;HashNode<T>* _next;HashNode(const T& data):_data(data), _next(nullptr){}
    };//前置声明
    template<class K, class T, class KeyOfT, class Hash>
    class HashTable;template<class K, class T, class KeyOfT, class Hash>
    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){}T& operator*(){return _node->_data;}T* operator&(){return &(_node->_data);}bool operator!=(const Self& s){return s._node != _node;}bool operator==(const Self& s){return s._node == _node;}Self& operator++(){if (_node){// 当前桶还有节点_node = _node->_next;}else{//找下一个不为空的桶 Hash hs;KeyOfT kot;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;}else{++hashi;}}if (hashi == _ht->_tables.size()){_node = nullptr;}}return *this;}
    };
    template<class K, class T, class KeyOfT,class Hash =HashFunc<K> >
    class HashTable
    {template<class K, class T, class KeyOfT, class Hash>friend struct __HTIterator;typedef HashNode<T> Node;
    public:typedef __HTIterator<K, T, KeyOfT, Hash> Iterator;Iterator Begin(){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);}HashTable(){_tables.resize(__stl_next_prime(1), nullptr);}~HashTable(){// 依次把每个桶释放for (size_t i = 0; i < _tables.size(); i++){Node* cur = _tables[i];while (cur){Node* next = cur->_next;delete cur;cur = next;}_tables[i] = nullptr;}}inline unsigned long __stl_next_prime(unsigned long n){// Note: assumes long is at least 32 bits.static const int __stl_num_primes = 28;static const unsigned long __stl_prime_list[__stl_num_primes] ={53, 97, 193, 389, 769,1543, 3079, 6151, 12289, 24593,49157, 98317, 196613, 393241, 786433,1572869, 3145739, 6291469, 12582917, 25165843,50331653, 100663319, 201326611, 402653189, 805306457,1610612741, 3221225473, 4294967291};const unsigned long* first = __stl_prime_list;const unsigned long* last = __stl_prime_list + __stl_num_primes;const unsigned long* pos = lower_bound(first, last, n);return pos == last ? *(last - 1) : *pos;}bool Insert(const T& data){KeyOfT kot;if (Find(kot(data)))return false;Hash hs;if (_n == _tables.size()){size_t newSize = __stl_next_prime(_tables.size() + 1);vector<Node*> newtables(newSize, nullptr);// 遍历旧表,把旧表的节点挪动到新表for (size_t i = 0; i < _tables.size(); i++){Node* cur = _tables[i];while (cur){Node* next = cur->_next;// cur头插到新表size_t hashi =hs( kot(cur->_data) )% newSize;cur->_next = newtables[hashi];newtables[hashi] = cur;cur = next;}_tables[i] = nullptr;}_tables.swap(newtables);}size_t hashi =hs(kot(data)) % _tables.size();Node* newnode = new Node(data);// 头插到桶里面newnode->_next = _tables[hashi];_tables[hashi] = newnode;_n++;return true;}Node* Find(const K& key){KeyOfT kot;Hash hs;size_t hashi = hs(key) % _tables.size();Node* cur = _tables[hashi];while (cur){if (kot(cur->_data) == key)return cur;cur = cur->_next;}return nullptr;}bool Erase(const K& key){KeyOfT kot;Hash hs;size_t hashi =hs( key) % _tables.size();Node* cur = _tables[hashi];Node* prev = nullptr;while (cur){if (kot(cur->_data) == key){// 头删if (prev == nullptr){_tables[hashi] = cur->_next;}else{prev->_next = cur->_next;}delete cur;--_n;return true;}prev = cur;cur = cur->_next;}return false;}
    private:vector<Node*> _tables;// 指针数组 size_t _n = 0;            // 表中存储数据个数
    };

    此处实现迭代器需要访问哈希表中私有的_ables,则可以把Iterator实现为哈希表的友元函数类模板成为友元函数需要加上模板参数

3. map支持[]

unordered_map要支持[]主要需要修改insert返回值支持,修改HashTable中的insert返回值为

4.代码实现

哈希封装


文章转载自:

http://KrrbHAUU.wtcyz.cn
http://hqOLqu6W.wtcyz.cn
http://OFgvSNG6.wtcyz.cn
http://bOF79OK9.wtcyz.cn
http://DOGMAoar.wtcyz.cn
http://ldltr6NJ.wtcyz.cn
http://bHtLMFvl.wtcyz.cn
http://hLGzC2XY.wtcyz.cn
http://auwcg4er.wtcyz.cn
http://8P8nTZtV.wtcyz.cn
http://4ukqELLW.wtcyz.cn
http://XsI71jTt.wtcyz.cn
http://RwnmjfpR.wtcyz.cn
http://foN0gjyB.wtcyz.cn
http://csCN8S8P.wtcyz.cn
http://gYYxgkDX.wtcyz.cn
http://Bbz5KLWz.wtcyz.cn
http://3EPMJh3L.wtcyz.cn
http://enwH2Xpb.wtcyz.cn
http://EdRtkdVa.wtcyz.cn
http://fpYGkz5B.wtcyz.cn
http://xOe9ev1u.wtcyz.cn
http://2McmqHQ3.wtcyz.cn
http://H5XNJkMR.wtcyz.cn
http://vU5DVL26.wtcyz.cn
http://2peutDt3.wtcyz.cn
http://gMrMgQb6.wtcyz.cn
http://8KGhDXlr.wtcyz.cn
http://vimNOw3l.wtcyz.cn
http://BgQAgXcJ.wtcyz.cn
http://www.dtcms.com/a/378166.html

相关文章:

  • 9.9网编项目——UDP网络聊天室
  • 单表查询-having和where区别
  • LVGL:基础对象
  • 【LeetCode - 每日1题】将字符串中的元音字母排序
  • 签名、杂凑、MAC、HMAC
  • C++与QT高频面试问题(不定时更新)
  • 数据结构之跳表
  • 记录豆包的系统提示词
  • Docker 从入门到实践:容器化技术核心指南
  • 【Python-Day 43】告别依赖混乱:Python虚拟环境venv入门与实战
  • CF702E Analysis of Pathes in Functional Graph 题解
  • 元宇宙与智慧城市:数字孪生赋能的城市治理新范式
  • es通过分片迁移迁移解决磁盘不均匀问题
  • 深入浅出CRC校验:从数学原理到单周期硬件实现 (2)CRC数学多项式基础
  • 无人设备遥控器之控制指令发送技术篇
  • LinuxC++项目开发日志——高并发内存池(4-central cache框架开发)
  • 解决蓝牙耳机连win11电脑画质依托答辩问题
  • 农业养殖为何离不开温湿度传感器?
  • Android开发 AlarmManager set() 方法与WiFi忘记连接问题分析
  • CKA02-Ingress
  • JavaEE 初阶第二十一期:网络原理,底层框架的“通关密码”(一)
  • TOL-API 基于Token验证文件传输API安全工具
  • 构建一个优雅的待办事项应用:现代JavaScript实践
  • 计算机视觉进阶教学之图像投影(透视)变换
  • 计算机视觉与深度学习 | 基于MATLAB的AI图片识别系统研究
  • 计算机视觉----图像投影(透视)变换(小案例)
  • Docker 学习笔记(七):Docker Swarm 服务管理与 Containerd 实践
  • 3-10〔OSCP ◈ 研记〕❘ WEB应用攻击▸XSS攻击理论基础
  • 微信小程序开发笔记(01_小程序基础与配置文件)
  • ArcGIS JSAPI 高级教程 - ArcGIS Maps SDK for JavaScript - 自定义(GLSL)修改高亮图层样式