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

【C++】哈希表的实现(链地址法)

1.其他哈希函数1.1 乘法散列法了解乘法散列法对哈希表⼤⼩M没有要求他的⼤思路第⼀步⽤关键字K 乘上常数 A(0A1)并抽取出k*A的⼩数部分第⼆步⽤M乘以k*A 的⼩数部分再向下取整。其实就是让M去乘一个[0, 1)之间的小数这个小数要与K相关K不同这个小数就不同就能映射的更分散。经过大佬Knuth的分析建议这个A取黄金分割点:A(\sqrt{5}-1)/2 0.6180339887....所以乘法散列法的公式为h(key) floor(M * (A * key) % 1.0))其中floor表⽰对表达式进⾏向下取整A∈(0,1)。举个例子乘法散列法对哈希表⼤⼩M是没有要求的假设M为1024key为1234A 0.6180339887, A*key 762.6539420558取⼩数部分为0.6539420558, M×((A×key)%1.0) 0.6539420558*1024 669.6366651392那么h(1234) 669。1.2 全域散列法了解这个函数主要是为了抵御恶意攻击的。如果存在⼀个恶意的对⼿他针对我们提供的散列函数特意构造出⼀个发⽣严重冲突的数据集 ⽐如让所有关键字全部落⼊同⼀个位置中。这种情况是可以存在的只要散列函数是公开且确定的就可以实现此攻击。解决⽅法就是给散列函数增加随机性攻击者就⽆法找出确定可以导致最坏情况的数据。这种⽅法叫做全域散列。全域散列法的公式为h(key) ((a * key b) % P) % MP需要选一个足够大的质数a可以随机选[1, P-1]之间的任意整数b可以随机选[0, P-1]之间的任意整数。这些函数构成了一个P * (P - 1)组全域散列函数组。假设key是8P17M6a 3 b 4, 则h(8) ((3 * 8 4) % 17) % 6 5。需要注意的是每次初始化哈希表 时 随机选取全域散列函数组中的⼀个散列函数使⽤后续增删查改都固定使⽤这个散列函数否则每次哈希都是随机选⼀个散列函数那么插⼊是⼀个散列函数查找⼜是另⼀个散列函数就会导致找不到插⼊的key了。2.处理哈希冲突的方法在开放定址法中所有的元素都放到哈希表⾥当⼀个关键字key⽤哈希函数计算出的位置冲突了则按照某种规则找到⼀个没有存储数据的位置进⾏存储开放定址法中负载因⼦⼀定是⼩于的。这⾥的规则有三种线性探测已做讲解、⼆次探测、双重探测。2.1 开放定址法性探测的⽐较简单且容易实现线性探测的问题假设hash0位置连续冲突hash0hash1hash2位置已经存储数据了后续映射到hash0hash1hash2hash3的值都会争夺hash3位置这种现象叫做群集/堆积。二次探测从发⽣冲突的位置开始依次左右按加减⼆次⽅跳跃式探测直到寻找到下⼀个没有存储数据的位置为⽌如果往右⾛到哈希表尾则回绕到哈希表头的位置如果往左⾛到哈希表头则回绕到哈希表尾的位置。h(key) hash0 key % M, hash0的位置冲突了则二次探测的公式为hc(key, i) hashi (hash0\pmi^{2}) % M, i { 1, 2, 3, ... ,\frac{M}{2}}。二次探测hashi (hash0 -i^{2}) % M 时hashi0时需要hashi M。把 {19,30,52,63,11,22} 等这⼀组值映射到M11的表中。h(19) 8, h(30) 8, h(52) 8, h(63) 8, h(11) 0, h(22) 0代码就不实现了。双重探测了解线性探测是挨着找空位二次探测是有规律的跳跃着找空位双重探测就是再弄一个哈希函数无规律的跳跃着找空位减少堆积。第⼀个哈希函数计算出的值发⽣冲突使⽤第⼆个哈希函数计算出⼀个跟key相关的偏移量值不断往后探测直到寻找到下⼀个没有存储数据的位置为⽌。h1 (key) hash0 key%M, hash0位置冲突了则双重探测公式为hc(key,i) hashi (hash0 i∗h2 (key)) %Mi {1, 2, 3, ...,M}2.2 链地址法前面的开放定址法不管是哪种探测还是会出现相互挤占位置的情况不能完全解决这个问题。更好的解决方法其实是链地址法。链地址法中所有的数据不再直接存储在哈希表中哈希表中存储⼀个指针没有数据映射这个位置时这个指针为空有多个数据映射到这个位置时我们把这些冲突的数据链接成⼀个链表挂在哈希表这个位置下⾯链地址法也叫做拉链法或者哈希桶。比如说把 {19,30,5,36,13,20,21,12,24,96} 等这⼀组值映射到M11的表中。h(19) 8 h(30) 8 h(5) 5 h(36) 3 h(13) 2 h(20) 9 h(21) 10 h(12) 1, h(24) 2, h(96) 8开放定址法负载因⼦必须⼩于1链地址法的负载因⼦就没有限制了可以⼤于1。负载因⼦越⼤哈希冲突的概率越⾼空间利⽤率越⾼负载因⼦越⼩哈希冲突的概率越低空间利⽤率越低stl中unordered_xxx的最⼤负载因⼦基本控制在1⼤于1就扩容。
http://www.gsyq.cn/news/1292369.html

相关文章:

  • 告别DLL地狱:VisualCppRedist AIO一站式解决Windows运行库依赖难题
  • Cool-Request全局请求头配置终极指南:告别重复配置的API测试新体验
  • RP2040内置温度传感器开发指南:从原理到实践
  • LiveDraw:Windows平台实时屏幕标注工具的完整使用指南
  • Cursor Pro破解终极指南:3种简单方法实现AI编程助手永久免费使用
  • tchMaterial-parser:3分钟掌握国家中小学智慧教育平台电子课本免费下载的完整指南
  • 免费专业级渲染器:Radeon ProRender Blender插件完整指南
  • 如何快速实现设计到动效的无缝转换:AEUX免费工具的完整指南
  • Polymarket预测市场自动化交易机器人:架构、策略与部署指南
  • 对比按需调用与Token Plan套餐在长期项目中的成本体感
  • 如何永久免费使用Cursor AI:Cursor Free VIP的终极破解指南
  • RISC-V PMP配置不当引发栈溢出:嵌入式内存保护调试实战
  • LSM6DS3TR-C与磁力计融合:Mahony算法实现高精度姿态解算
  • 明日方舟终极自动化助手:MAA智能辅助工具完整实战指南
  • 手把手教你用Python+statsmodels做广告效果归因:从数据清洗、建模到剔除无效渠道(附完整代码)
  • 基于Stable Diffusion与ControlNet的AI图像编辑工作室:架构、工作流与调优实践
  • Path of Building终极指南:流放之路Build规划完整教程
  • WeChatPad终极指南:三步实现微信双设备登录的简单方案
  • CIDR.xyz:网络工程师必备的在线子网计算与IP规划工具
  • VSCode集成AI代理:基于MCP协议的智能编程助手实战
  • 为什么开源PCB查看器正在改变硬件工程师的工作方式?
  • D2RML终极指南:暗黑2重制版一键多开神器,效率提升400%
  • GEE实战指南:从数据导出到本地分析,掌握SHP与CSV的Export全流程
  • 别只盯着删不删!深入聊聊Python __pycache__ 的设计哲学与性能取舍
  • Deepin Boot Maker:Linux启动盘制作的智能化解决方案
  • MacType终极指南:彻底解决Windows字体模糊问题的免费神器
  • 构建垂直领域RAG引擎:从检索增强生成到人才招聘智能问答实践
  • Cursor编辑器集成GitHub Copilot:桥接器部署与调优指南
  • 具身智能论文清单:HCPLab开源项目助力高效学术研究
  • BIRD网络守护进程:轻量级动态路由在边缘计算与容器网络中的实践