新闻详情

新闻详情

首页 / 资讯中心 / 详情

C++哈希表的实现

发布时间:2026/9/10 21:18:09来源:尧图网络
C++哈希表的实现
文章目录哈希的概念直接定址法哈希冲突负载因子将关键字转为整数哈希函数除法散列法/除流余数法处理哈希冲突开放定址法hash框架hash定义插入查找删除整体代码测试代码哈希的概念哈希又称散列是一种组织数据的方式。从译名来看有散乱排列的意思。本质就是通过哈希函数把关键字key跟存储位置建立一个映射关系查找时通过这个哈希函数计算出key存储的位置进行快速查找。直接定址法当关键字的范围比较集中直接定址法就是简单高效的方法比如一组关键字都在[0,99]之间那么我们开一个100个数的数组每个关键字的值直接就是存储位置的小标。也就是说直接定址法本质就是用关键字计算出一个绝对位置或者相对位置。哈希冲突直接定址法的缺点也非常明显当关键字的范围比较分散时就很浪费内存甚至内存不够用。假设我们只要数据范围[0,9999]的N个值我们要映射到一个M个空间的数组中MN,那么就要借助哈希函数关键字key被放到数组h(key)位置这里要注意的是h(key)计算的值必须在[0,M)之间。这里存在的一个问题就是两个不同的key可能会映射到同一个位置去这种问题叫哈希冲突或者哈希碰撞。理想情况下是找出一个好的哈希函数避免冲突但是实际场景中冲突是不可避免的我们只能尽可能去减少冲突的次数。负载因子假设哈希表中已经映射存储N个值哈希表的大小是M,那么负载因子 N/M,负载因子越大哈希冲突的概率就越高空间利用率越高负载因子越小哈希冲入的概率越低空间利用率越低将关键字转为整数我们将关键字映射到数组中位置一般是整数好做映射计算如果不是整数我们要想办法转化成整数。哈希函数一个好的哈希函数应该让N个关键字被等概率的均匀的散列分布到哈希表的M个空间中但是实际中很难做到。除法散列法/除流余数法假设哈希表的大小为M,那么通过key除以M的余数作为映射位置的下标也就是哈希函数为h(key) key%M。当使用除法散列法时建议M取不太接近2的整数次幂的一个质数。处理哈希冲突实践中哈希表一般还是选择除法散列作为哈希函数当然哈希表无论选择什么哈希函数也避免不了冲突解决冲突主要有两种方法开放定址法和链地址法。开放定址法在开放定址法中所有元素都放到哈希表里当一个关键字key用哈希函数计算出位置冲突了则按照某种规则找到一个没有存储数据的位置进行存储开放定址法中负载因子一定是小于的。这里的规则有三种线性探测二次探测双重探测。线性探测从发生冲突的位置开始依次线性向后探测直到寻到下一个没有存储数据的位置为止如果走到哈希表尾则回绕到哈希表头的位置。h(key) hash0 key%M,hash0位置冲突了则线性探测公式为hc(key,i) hashi (hash0i)%M, i{1,2,3,…,M-1},因为负载因子小于1则最多探测M-1次一定能找到一个存储位置key的位置。线性探测的比较简单且容易实现线性探测的问题假设hash0位置连续冲突hash0,hash1,hash2位置已经存储数据了后续映射到hash0,hash1,hash2,hash3的值都会争夺hash3位置这种现象叫群集/堆积。hash框架hash定义切记删除的时候不可以直接删除要进行定义其当前的状态防止直接删除。enumState{EXIST,EMPTY,DELETE};templateclassK,classVstructHashData{pairK,V_kv;State _stateEMPTY;};templateclassK,classVclassHashTable{public:HashTable():_tables(11),_n(0){}private:vectorHashDataK,V_tables;size_t _n;//表中存储的数据个数};插入boolInsert(constpairK,Vkv){//扩容 负载因子if(_n*10/_tables.size()7){//扩2倍效率底且无法保证是质数/*vectorHashDataK, V newtables(_table.size() * 2); for (auto data : _tables) { if (data._state EXIST) { size_t hash0 data.first % newtables.size(); size_t hashi hash0; size_t i 1; while (newtables[hahsi]._state EXIST) { hashi (hash0 i) % newtables.size(); i; } newtables[hashi]._kv kv; newtables[hashi]._state EXIST; } }*/HashTableK,Vnewht;newht._tables.resize(_tables.size()*2);for(autodata:_tables){//旧表的数据映射到新表if(data._stateEXIST){newht.Insert(data._kv);}}_nnewht._n;_tables.swap(newht._tables);}size_t hash0kv.first%_tables.size();size_t hashihash0;size_t i1;while(_tables[hashi]._stateEXIST){//线性探测hashi(hash0i)%_tables.size();i;}_tables[hashi]._kvkv;_tables[hashi]._stateEXIST;_n;returntrue;}查找HashDataK,V*Find(constKkey){size_t hash0key%_tables.size();size_t hashihash0;size_t i1;while(_tables[hashi]._state!EMPTY){if(_tables[hashi]._state!DELETE_tables[hashi]._kv.firstkey){return_tables[hashi];}else{hashi(hash0i)%_tables.size();i;}}returnnullptr;}删除boolErase(constKkey){HashDataK,V*retFind(key);if(ret){ret-_stateDELETE;returntrue;}returnfalse;}整体代码#pragmaonce#includeiostream#includevectorusingnamespacestd;enumState{EXIST,EMPTY,DELETE};templateclassK,classVstructHashData{pairK,V_kv;State _stateEMPTY;};templateclassK,classVclassHashTable{public:HashTable():_tables(11),_n(0){}boolInsert(constpairK,Vkv){//扩容 负载因子if(_n*10/_tables.size()7){//扩2倍效率底且无法保证是质数/*vectorHashDataK, V newtables(_table.size() * 2); for (auto data : _tables) { if (data._state EXIST) { size_t hash0 data.first % newtables.size(); size_t hashi hash0; size_t i 1; while (newtables[hahsi]._state EXIST) { hashi (hash0 i) % newtables.size(); i; } newtables[hashi]._kv kv; newtables[hashi]._state EXIST; } }*/HashTableK,Vnewht;newht._tables.resize(_tables.size()*2);for(autodata:_tables){//旧表的数据映射到新表if(data._stateEXIST){newht.Insert(data._kv);}}_nnewht._n;_tables.swap(newht._tables);}size_t hash0kv.first%_tables.size();size_t hashihash0;size_t i1;while(_tables[hashi]._stateEXIST){//线性探测hashi(hash0i)%_tables.size();i;}_tables[hashi]._kvkv;_tables[hashi]._stateEXIST;_n;returntrue;}HashDataK,V*Find(constKkey){size_t hash0key%_tables.size();size_t hashihash0;size_t i1;while(_tables[hashi]._state!EMPTY){if(_tables[hashi]._state!DELETE_tables[hashi]._kv.firstkey){return_tables[hashi];}else{hashi(hash0i)%_tables.size();i;}}returnnullptr;}boolErase(constKkey){HashDataK,V*retFind(key);if(ret){ret-_stateDELETE;returntrue;}returnfalse;}private:vectorHashDataK,V_tables;size_t _n;};测试代码#includeiostream#includeset#includeunordered_setusingnamespacestd;#includeHashTable.hvoidtest1(){unordered_setints{3,1,6,7,8,2};unordered_setint::iterator its.begin();while(it!s.end()){cout*it ;it;}coutendl;}voidtest2(){constsize_t N1000000;unordered_setintus;setints;vectorintv;v.reserve(N);srand(time(0));for(size_t i0;iN;i){v.push_back(rand()i);}size_t begin1clock();for(autoe:v){us.insert(e);}size_t end1clock();coutset:end1-begin1endl;size_t begin2clock();us.reserve(N);for(autoe:v){s.insert(e);}size_t end2clock();coutunordered_set:end2-begin2endl;}voidtest3(){inta[]{19,30,52,63,11,12,22,35,31};HashTableint,intht;for(autoe:a){ht.Insert({e,e});}intx30;if(ht.Find(x)){cout找到了endl;}ht.Erase(x);if(ht.Find(x)){cout找到了endl;}else{cout没找到了endl;}}intmain(){test3();return0;}觉得我回答有用的话记得点个关注哟谢谢支持
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

一条命令跑通自建电子签名平台:DocuSeal 2026/9/10 22:09:16

一条命令跑通自建电子签名平台:DocuSeal

一条命令跑通自建电子签名平台:DocuSeal 【免费下载链接】docuseal Open source DocuSign alternative. Create, fill, and sign digital documents ✍️ 项目地址: https://gitcode.com/GitHub_Trending/do/docuseal 周五下班前,还有一份合同要发出去,对方得签字,你只能…

阅读更多 →
Elixir Pro Agent 深度解析:基于 OTP、Phoenix 与 BEAM 的函数式编程专家在 agents24 中的设计与应用 2026/9/10 22:09:16

Elixir Pro Agent 深度解析:基于 OTP、Phoenix 与 BEAM 的函数式编程专家在 agents24 中的设计与应用

Elixir Pro Agent 深度解析:基于 OTP、Phoenix 与 BEAM 的函数式编程专家在 agents24 中的设计与应用 【免费下载链接】agents Multi-harness agentic plugin marketplace for Claude Code, Codex, Cursor, OpenCode, GitHub Copilot, and Google Antigravity 项目…

阅读更多 →
Semgrep 静态代码扫描实战指南:用几行命令跑通首次安全扫描 2026/9/10 22:09:16

Semgrep 静态代码扫描实战指南:用几行命令跑通首次安全扫描

Semgrep 静态代码扫描实战指南:用几行命令跑通首次安全扫描 【免费下载链接】semgrep Lightweight static analysis for many languages. Find bug variants with patterns that look like source code. 项目地址: https://gitcode.com/GitHub_Trending/se/semgre…

阅读更多 →
CANN/ge图引擎RunGraph接口 2026/9/10 22:09:16

CANN/ge图引擎RunGraph接口

RunGraph 【免费下载链接】ge GE(Graph Engine)是面向昇腾的图编译器和执行器,提供了计算图优化、多流并行、内存复用和模型下沉等技术手段,加速模型执行效率,减少模型内存占用。 GE 提供对 PyTorch、TensorFlow 前端的…

阅读更多 →
Ricon组态系统与物联网平台集成实践指南 2026/9/10 22:09:16

Ricon组态系统与物联网平台集成实践指南

1. Ricon组态系统与物联网平台集成概述 在工业自动化领域,组态系统作为人机交互的核心枢纽,与物联网平台的深度融合已成为数字化转型的关键路径。Ricon作为国内主流的组态软件,其与物联网平台的集成方案能够实现设备数据的统一采集、可视化监…

阅读更多 →
Kivy跨平台应用开发实战与架构解析 2026/9/10 22:06:16

Kivy跨平台应用开发实战与架构解析

1. 为什么选择Kivy开发跨平台应用? 在移动应用开发领域,开发者经常面临一个关键抉择:是为每个平台单独开发原生应用,还是采用跨平台方案?我五年前接手一个需要同时支持Android和iOS的项目时,经过多轮技术选…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞