news 2026/4/3 7:37:39

哈希表全解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
哈希表全解析

🔍 哈希表全解析:让“找东西”快如闪电的秘密武器!

想象一下:你在100万人的名单里找“张三”。
普通列表要查100万次,二分查找也要20次——
但哈希表?1次命中!

这背后,是一套精妙的“地址翻译系统”:哈希函数 + 冲突处理策略
今天,我们就用真实例子 + 逐步演示 + 关键公式,彻底讲透哈希表的每一个细节!


一、基本概念

🎯 哈希函数

将关键字key映射为存储地址的函数 。理想情况下,无需比较即可直接定位。

⚠️ 冲突与同义词

  • 冲突:不同关键字映射到同一地址。

  • 同义词:发生冲突的关键字互称同义词。

💡 例:H(key) = key % 7→ H(15)=1, H(22)=1 → 冲突!


二、哈希函数构造6法(附例子)


三、冲突处理4大技术

统一设定

  • 关键字序列:47, 7, 29, 11, 16, 92, 22, 8, 3

  • 哈希函数:(地址0~10)

  • 初始哈希地址:

key

H

47

3

7

7

29

7 ❗

11

0

16

5

92

4

22

0 ❗

8

8

3

3 ❗


1. 开放定址法(Open Addressing)

所有元素必须存放在主表中,冲突时在表内探测新位置。

(1)线性探测:挨家挨户问
  • 规则

✅ 插入结果:

地址

0

1

2

3

4

5

6

7

8

9

10

元素

11

22

47

92

16

3

7

29

8

🔍 查找8:H=8 → 29≠8 → 9 → 找到(2次)
⚠️ 缺点:一次聚集严重。


(2)二次探测:跳跃式找房
  • 规则,顺序:+1, -1, +4, -4...

✅ 插入关键步骤:

  • 3(H=3):+1→4(占),-1→2(空) → 存入2

✅ 最终表:

地址

0

1

2

3

4

5

6

7

8

9

10

元素

11

22

3

47

92

16

7

29

8

✅ 优势:减少聚集,分布更均匀。


(3)伪随机探测:按“神秘清单”找房
  • 规则预设一个伪随机序列
    探测地址:

📌 常见做法:用线性同余生成器产生固定序列,如,种子固定 → 序列可重现

我们预设随机偏移序列:R = [3, 5, 2, 7, 1, 4, 6, 8, 9]

🔧 逐个插入(只看冲突项):
  • 29(H=7)

    • 7 被7占用 → 试 (7+3)%11 = 10 → 空 →存入10

  • 22(H=0)

    • 0 被11占用 → 试 (0+3)%11=3(47占)

    • 试 (0+5)%11=5(16占)

    • 试 (0+2)%11=2 → 空 →存入2

  • 3(H=3)

    • 3(47占)→ +3→6(空?是!)→存入6

注:8 的 H=8,此时仍为空(29已去10),所以8直接存入8。

最终表

地址

0

1

2

3

4

5

6

7

8

9

10

元素

11

22

47

92

16

3

7

8

29

🔍 查找29:H=7 → 7≠29 → 试10 → 找到(2次)
✅ 优势:探测路径看似随机,有效打破聚集;
⚠️ 缺点:需额外存储/生成随机序列,实现稍复杂。


2. 再哈希法(Double Hashing)

  • 规则

✅ 最终表:

地址

0

1

2

3

4

5

6

7

8

9

10

元素

11

3

8

47

92

16

22

7

29

✅ 优势:探测步长由 key 决定,几乎无聚集


3. 链地址法(Chaining)

每个地址挂一个链表。

✅ 最终结构:

0: 22 → 11 3: 3 → 47 4: 92 5: 16 7: 29 → 7 8: 8

✅ 优势:无聚集、删除简单、支持 α > 1 ——工业界首选


4. 公共溢出区(Public Overflow Area)

规则:主表只存“第一个来的”; 后续冲突者按插入顺序进入溢出区; 溢出区是线性数组,不按哈希地址分配位置!

🔧 结果: ✅ 主表:

地址

0

3

4

5

7

8

元素

11

47

92

16

7

8

✅ 溢出区(按插入顺序!):

序号

key

原始 H

0

29

7

1

22

0

2

3

3

🔍查找 3:H=3 → 主表[3]=47 ≠ 3
遍历溢出区:29(H=7)→22(H=0)→3(H=3 ✔) → 找到(3次)

一共进行四次比较

🚨重点澄清:溢出区是时间顺序队列,不是按 H 分组!
仅适合冲突极少的场景(α < 0.1),否则退化为 O(n)

四、查找与插入算法(开放定址伪代码)

// 线性探测示例 SearchHash(HT, key): addr = key % m while HT[addr] ≠ key and HT[addr] ≠ EMPTY: addr = (addr + 1) % m return (HT[addr] == key) ? addr : NOT_FOUND

五、性能分析

装填因子 α = n / m

ASL 公式(查找成功):

  • 线性探测:

  • 二次/再哈希:

  • 链地址:

α=0.8 时:线性探测 ASL≈3.0,链地址≈1.4


六、结论与选型建议

方法

推荐场景

链地址法

通用首选(HashMap、dict)

再哈希法

高性能、内存受限

线性探测

小数据、静态表

二次/伪随机探测

需避免聚集的开放定址场景

公共溢出区

冲突极少

✅ 默认选择:除留余数法 + 链地址法


💡 结语

从线性探测到链地址,从伪随机到再哈希——哈希表的每一种策略,都是对“冲突”这一现实问题的智慧回应。

掌握它们,你就能在工程与面试中游刃有余!


📚 动手画一遍9个关键字的插入过程,胜过十遍阅读!
👉 觉得有用?点赞+转发!
❓ 你在项目中用哪种方法?欢迎留言!


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

Sambert GPU温度监控:高温降频问题规避实战

Sambert GPU温度监控&#xff1a;高温降频问题规避实战 1. 引言&#xff1a;为什么语音合成服务也需要关注GPU温度&#xff1f; 你有没有遇到过这种情况&#xff1a;刚部署好的Sambert语音合成服务&#xff0c;第一次生成声音又快又自然&#xff0c;但连续处理几个请求后&…

作者头像 李华
网站建设 2026/4/3 6:11:12

零代码生成专属音色|基于科哥开发的Voice Sculptor镜像快速上手

零代码生成专属音色&#xff5c;基于科哥开发的Voice Sculptor镜像快速上手 你是否想过&#xff0c;自己也能拥有一个独一无二的声音&#xff1f;不是模仿某个明星&#xff0c;而是真正属于你的“声纹”——可以是温暖治愈的冥想导师、磁性低沉的纪录片旁白&#xff0c;或是活…

作者头像 李华
网站建设 2026/3/31 13:31:44

为什么Qwen3-4B部署慢?镜像自动启动优化教程揭秘

为什么Qwen3-4B部署慢&#xff1f;镜像自动启动优化教程揭秘 1. Qwen3-4B部署为何总在“卡启动”&#xff1f; 你是不是也遇到过这种情况&#xff1a;好不容易选好配置&#xff0c;点击部署Qwen3-4B-Instruct-2507镜像&#xff0c;进度条走完后却迟迟打不开网页推理界面&…

作者头像 李华
网站建设 2026/3/14 11:59:09

对比实测:自己搭环境 vs 使用预置镜像微调效率差异

对比实测&#xff1a;自己搭环境 vs 使用预置镜像微调效率差异 你是否也曾经被“大模型微调”这个词吓退&#xff1f;总觉得需要庞大的算力、复杂的配置、动辄几天的调试时间&#xff1f;其实&#xff0c;随着工具链的成熟和生态的完善&#xff0c;一次完整的 LoRA 微调&#…

作者头像 李华
网站建设 2026/4/2 9:14:00

Z-Image-Turbo生成动漫角色全过程分享

Z-Image-Turbo生成动漫角色全过程分享 1. 引言&#xff1a;为什么选择Z-Image-Turbo来创作动漫角色&#xff1f; 你有没有想过&#xff0c;只需一段文字描述&#xff0c;就能瞬间生成一张细节丰富、风格鲜明的动漫角色图&#xff1f;这不再是科幻场景。借助阿里通义实验室开源…

作者头像 李华
网站建设 2026/3/31 5:22:46

创建型模式:简单工厂模式(C语言实现)

作为C语言开发者&#xff0c;我们每天都在和各种“对象”打交道——传感器、外设、缓冲区、任务控制块……尤其是做嵌入式开发时&#xff0c;经常要写一堆类似的初始化代码&#xff1a;温度传感器要初始化I2C接口&#xff0c;光照传感器要配置SPI时序&#xff0c;湿度传感器又要…

作者头像 李华