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

【C++】用哈希表封装unordered_XX

目录

1. 复用哈希表

2. Iterator和ConstIterator的实现

3. 实现unordered_set

4. 实现unordered_map

5. 完整代码


本篇文章我们要实现unodered_map和unodered_set,基本的大致思路其实和前面map和set的封装差不多:【C++】map和set的封装-CSDN博客

所以相同的内容我就不再赘述了,本篇主要就是展示一下大致思路,代码部分偏多,大家可以一起试试实现一下哦!

1. 复用哈希表

我们在前面的文章中就已经实现过哈希表了:【C++】哈希表的实现-CSDN博客

本篇文章中实现unordered_map和unordered_set复用的是用链地址法实现的哈希表(即哈希桶)

在此基础上稍作改动:

//解决有些key不能取模的问题
template<class K>
struct HashKey
{//能转化成size_t的,就直接转换size_t operator()(const K& k){return size_t(k);}
};//特化
template<>
struct HashKey<string>
{size_t operator()(const string& s){size_t ret = 0;for (auto e : s){ret *= 31;ret += e;}return ret;}};
//链地址法
namespace hash_bucket
{template<class T>struct HashNode{T _data;HashNode* _next;HashNode(const T& data):_data(data), _next(nullptr){}};template<class K,class T,class KeyOfT,class Hash = HashKey<K>>class HashTable {public:typedef HashNode<T> Node;HashTable(){_tables.resize(__stl_next_prime(0),nullptr);}~HashTable(){for (int i = 0; i < _tables.size(); i++){while (_tables[i]){Node* del = _tables[i];_tables[i] = _tables[i]->_next;delete del;del = nullptr;}}_size = 0;}bool Insert(const T& data){KeyOfT kot;Hash h;if (Find(kot(data)))return false;//负载因子大于0.7——扩容if ((double)_size / (double)_tables.size() > 0.7){vector<Node*> newHT;newHT.resize(__stl_next_prime((unsigned long)_tables.size() + 1), nullptr);for (int i = 0; i < _tables.size(); i++){while(_tables[i]){size_t hash0 = h(kot(_tables[i]->_data)) % newHT.size();Node* newnode = _tables[i];_tables[i] = newnode->_next;newnode->_next = newHT[hash0];newHT[hash0] = newnode;}}newHT.swap(_tables);}Node* newnode = new Node(data);size_t hash0 = h(kot(data)) % _tables.size();//头插newnode->_next = _tables[hash0];_tables[hash0] = newnode;_size++;return true;}Node* Find(const K& key){Hash h;KeyOfT kot;size_t hash0 = h(key) % _tables.size();for (int i = 0; i < _tables.size(); i++){Node* cur = _tables[i];while (cur){if (kot(cur->_data) == key){return cur;}cur = cur->_next;}}return nullptr;}bool Erase(const K& key){Hash h;KeyOfT kot;size_t hash0 = h(key) % _tables.size();for (int i = 0; i < _tables.size(); i++){Node* cur = _tables[i];Node* prev = nullptr;while (cur){if (kot(cur->_data) == key){if (prev == nullptr)_tables[i] = cur->_next;else{prev->_next = cur->_next;}delete cur;cur = nullptr;_size--;return true;}prev = cur;cur = cur->_next;}}return false;}private: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;}vector<Node*> _tables;size_t _size = 0;};
}

2. Iterator和ConstIterator的实现

template<class K, class T, class KeyOfT, class Hash>
class HashTable;template<class K,class T,class Ref,class Ptr,class KeyOfT,class Hash>
struct HTIterator
{typedef HashNode<T> Node;typedef HashTable<K, T, KeyOfT, Hash> HT;typedef HTIterator<K, T, Ref, Ptr, KeyOfT, Hash> Self;Node* _node;const HT* _ht;HTIterator(Node* node,const HT* ht):_node(node),_ht(ht){}Ref operator*(){return _node->_data;}Ptr operator->(){return &_node->_data;}bool operator==(const Self& s){return _node == s._node;}bool operator!=(const Self& s){return _node != s._node;}Self& operator++(){if (_node->_next){_node = _node->_next;}else{KeyOfT kot;Hash h;size_t hashi = h(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 = HashKey<K>>
class HashTable {// 友元声明template<class K, class T, class Ref, class Ptr, class KeyOfT, class Hash>friend struct HTIterator;public:typedef HashNode<T> Node;typedef HTIterator<K, T, T&, T*, KeyOfT, Hash> Iterator;typedef HTIterator<K, T, const T&, const T*, KeyOfT, Hash> ConstIterator;Iterator Begin(){size_t hashi = 0;while (!_tables[hashi]){hashi++;}return Iterator(_tables[hashi], this);}Iterator End(){return Iterator(nullptr, this);}ConstIterator Begin()const{size_t hashi = 0;while (!_tables[hashi]){hashi++;}return ConstIterator(_tables[hashi], this);}ConstIterator End()const{return ConstIterator(nullptr, this);}//...
};

3. 实现unordered_set

完整代码:

#include"Hash.h"namespace yfr
{template<class K,class Hash = HashKey<K>>class unodered_set{struct SetKeyOfT{const K& operator()(const K& key){return key;}};public://typedef typename hash_bucket::HashTable<K, K, SetKeyOfT, Hash>::Iterator Iterator;//typedef typename hash_bucket::HashTable<K, K, SetKeyOfT, Hash>::ConstIterator ConstIterator;using Iterator = typename hash_bucket::HashTable <K, K, SetKeyOfT, Hash>::Iterator;using ConstIterator = typename hash_bucket::HashTable <K, K, SetKeyOfT, Hash>::ConstIterator;Iterator begin(){return _ht.Begin();}Iterator end(){return _ht.End();}ConstIterator begin() const{return _ht.Begin();}ConstIterator end() const{return _ht.End();}bool insert(const K&key){return _ht.Insert(key);}hash_bucket::HashNode<K>* find(const K& key){return _ht.Find(key);}bool erase(const K& key){return _ht.Erase(key);}private:hash_bucket::HashTable<K, K, SetKeyOfT,Hash> _ht;};
}

4. 实现unordered_map

完整代码:

namespace yfr
{template<class K,class V,class Hash= HashKey<K>>class undered_map{struct MapKeyOfT{const K& operator()(const pair<K, V>& kv){return kv.first;}};public:typedef typename hash_bucket::HashTable<K, pair<K, V>, MapKeyOfT, Hash>::Iterator Iterator;typedef typename hash_bucket::HashTable<K, pair<K, V>, MapKeyOfT, Hash>::ConstIterator ConstIterator;Iterator begin(){return _ht.Begin();}Iterator end(){return _ht.End();}ConstIterator begin() const{return _ht.Begin();}ConstIterator end() const{return _ht.End();}bool insert(const pair<K, V>& p){return _ht.Insert(p);}hash_bucket::HashNode<pair<K,V>>* find(const K& key){return _ht.Find(key);}bool erase(const K& key){return _ht.Erase(key);}private:hash_bucket::HashTable<K, pair<K, V>, MapKeyOfT, Hash> _ht;};
}

5. 完整代码

各位可以去这里看完整代码:unodered_xxx/unodered_xxx/Hash.h · 大白同学/C++进阶学习 - Gitee.com

http://www.dtcms.com/a/352410.html

相关文章:

  • 西游记24-26:万寿山,五庄观,镇元子;猴子偷果,猪八戒吃人参果——食而不知其味;逃跑被抓回,替师傅受罚;到处求仙,最终观音菩萨救树
  • Qt数据结构与编码技巧全解析
  • LeetCode 2140. 解决智力问题
  • 力扣(滑动窗口最大值)
  • LeetCode 刷题【53. 最大子数组和】
  • 一篇文章拆解Java主流垃圾回收器及其调优方法。
  • 详解 torch.distributed.all_gather_into_tensor
  • 15.examples\01-Micropython-Basics\demo_yield_task.py 加强版
  • 【实时Linux实战系列】基于实时Linux的生物识别系统
  • #Linux内存管理学以致用# 请你根据linux 内核struct page 结构体的双字对齐的设计思想,设计一个类似的结构体
  • 【测试需求分析】-需求来源分析(一)
  • 博士招生 | 香港大学 Intelligent Communication Lab 招收全奖博士
  • 【deepseek问答记录】:chatGPT的参数数量和上下文长度有关系吗?
  • AI Agent正在给传统数据仓库下“死亡通知书“
  • 读《精益数据分析》:用户行为热力图
  • 【拍摄学习记录】01-景别
  • 创龙3576ububuntu系统设置静态IP方法
  • 【Linux 进程】进程程序替换详解
  • 8.26网络编程——Modbus TCP
  • Git 高级技巧:利用 Cherry Pick 实现远程仓库的同步合并
  • 【自然语言处理与大模型】微调数据集如何构建
  • docker 的网络
  • shell默认命令替代、fzf
  • RCC_APB2PeriphClockCmd
  • sdi开发说明
  • 推荐系统王树森(三)粗排精排
  • STM32的Sg90舵机
  • Python入门教程之字符串类型
  • 日语学习-日语知识点小记-构建基础-JLPT-N3阶段(20):文法+单词第7回2
  • iPhone 17 Pro 全新配色确定,首款折叠屏 iPhone 将配备 Touch ID 及四颗镜头