S19 哈希--6种哈希构造方法

6 种经典哈希函数构造方法

哈希函数的核心作用是将任意长度的输入(关键字)映射到固定长度的输出(哈希地址),其设计直接影响哈希表的查找效率

1.什么是哈希?

哈希(Hash,也称为散列)是一种将任意长度的数据通过特定哈希函数(Hash Function)转换为固定长度值(哈希值,Hash Value,也叫散列值 、哈希码 、摘要)的过程。

1.直接定址法

1. 核心原理

直接使用关键字本身(或关键字的线性变换)作为哈希地址,无需复杂计算。

公式:H(key) = a × key + bab 为常数,通常 a=1b=0,即 H(key)=key)。

2. 示例

  • 关键字:{1001, 1002, 1003, 1004}(员工工号);

  • 哈希地址:H(key) = key - 1000 → 地址 {1, 2, 3, 4}

3. 优缺点

优点 缺点
1. 无冲突(映射唯一);2. 查找效率极高(O (1),无需处理冲突);3. 实现简单 1. 仅适用于关键字范围较小且连续的场景;2. 关键字范围过大时,哈希表空间浪费严重(如关键字是 1000-1000000,需分配 999001 个地址)

4. 适用场景

关键字为连续整数(如工号、学号、订单号),且范围可控(如 1-10000)。

2.数字分析法

1. 核心原理

针对 "关键字是数字(如身份证号、手机号)" 的场景,分析关键字的各位数字分布特征,选择分布均匀、重复性低的若干位作为哈希地址 ------ 避免选择重复率高的位(如身份证号的前 6 位是地址码,重复率高;后 4 位是顺序码 + 校验码,分布均匀)。

2. 示例

  • 关键字:{110105199001011234, 110105199102025678, 110105199203039012}(身份证号);

  • 分析:前 6 位(110105)是地区码(重复),中间 8 位是出生日期(部分重复),后 4 位(1234、5678、9012)分布均匀;

  • 哈希地址:取后 4 位 → 地址 {1234, 5678, 9012}(若地址范围过大,可再取后 2 位:{34, 78, 12})。

3. 优缺点

优点 缺点
1. 冲突概率低(基于数字分布特征选择,均匀性好);2. 充分利用关键字本身信息,无需额外计算 1. 仅适用于数字型关键字;2. 依赖关键字的数字分布特征(若所有位重复率都高,则无法使用);3. 需提前分析关键字样本

4. 适用场景

数字型关键字(身份证号、手机号、银行卡号),且关键字有明显的均匀分布位。

3.平方取中法

1. 核心原理

将关键字平方后,取中间的若干位作为哈希地址 ------ 平方后中间位的数字会受到关键字所有位的影响,分布更均匀,适用于关键字位数较少且分布不规则的场景。

2. 示例

  • 关键字:{12, 34, 56, 78}(2 位数字);

  • 平方后:12²=14434²=115656²=313678²=6084

  • 取中间 2 位:44(144 中间)、15(1156 中间)、13(3136 中间)、08(6084 中间);

  • 哈希地址:{44, 15, 13, 08}

3. 优缺点

优点 缺点
1. 分布均匀(平方后中间位受所有位影响);2. 适用于关键字位数少、分布不规则的场景;3. 无需提前分析关键字 1. 计算量略大(需平方运算);2. 关键字位数过多时,平方后数值可能溢出(需处理大数)

4. 适用场景

短数字关键字(如 1-4 位整数),且关键字分布无明显规律(如随机生成的编号)。

4.折叠法

1. 核心原理

将关键字(数字或字符串转数字)按固定长度分割成若干段,然后通过 "叠加(求和)" 或 "移位叠加" 的方式合并这些段,结果作为哈希地址 ------ 适用于关键字位数较多(如 10 位以上)的场景。

2. 两种折叠方式

方式 原理 示例(关键字:12345678,分割长度 = 2)
移位叠加 各段按右对齐叠加(末位对齐) 分割为 12、34、56、78 → 12+34+56+78=180 → 地址 = 180(若地址范围过大,可取模:180%100=80)
边界叠加 奇数段反转后再叠加(减少冲突) 分割为 12、34、56、78 → 反转奇数段(12→21、56→65)→ 21+34+65+78=198 → 地址 = 198

3. 优缺点

优点 缺点
1. 适用于长关键字(如 10 位以上数字、长字符串);2. 分布均匀(分割后叠加,弱化局部重复);3. 实现简单 1. 冲突概率略高于平方取中法;2. 分割长度需合理选择(过短易冲突,过长无意义)

4. 适用场景

长数字关键字(如 10 位以上工号、设备编号),或长字符串关键字(转数字后分割)。

5.除留余数法

1. 核心原理

最常用、最通用的构造方法:用关键字除以一个常数 m(哈希表的大小),取余数作为哈希地址。公式:H(key) = key mod mmod 为取余运算)。

2. 关键:m 的选择(决定冲突概率)

m 的选择直接影响哈希地址的均匀性,需遵循 3 个原则:

  1. m 最好是质数 (素数):避免关键字与 m 有公因数,导致地址集中(如 m=10,关键字是偶数时,地址仅为 0、2、4、6、8,分布不均);

  2. m 不宜过小(否则地址范围不足,冲突率高),也不宜过大(浪费空间);

  3. m 应略大于哈希表的预期存储容量(如预期存 100 个元素,m=101(质数))。

3. 示例

  • 关键字:{12, 34, 56, 78, 90}

  • 选择 m=11(质数);

  • 哈希地址:12 mod11=134 mod11=1(冲突)、56 mod11=1(冲突)、78 mod11=1090 mod11=2 → 地址 {1,1,1,10,2}(冲突需通过开放定址法 / 链地址法解决)。

4. 优缺点

优点 缺点
1. 通用性强(适用于所有数字型关键字,字符串可转数字后使用);2. 实现极简单;3. 哈希表空间利用率高(m 可灵活调整) 1. 冲突概率依赖 m 的选择(非质数时易冲突);2. 关键字分布不均时,冲突率可能较高

5. 适用场景

所有场景(数字关键字、字符串关键字转数字后),是实际开发中最常用的构造方法(如 HashMap、HashTable 底层默认使用类似逻辑)。

6.随机数法

1. 核心原理

引入随机函数,用关键字作为随机种子,生成一个 0~m-1m 为哈希表大小)的随机数,作为哈希地址。公式:H(key) = random(key) mod mrandom(key) 是以 key 为种子的随机函数)。

2. 示例

  • 关键字:{ "apple", "banana", "orange" }(字符串);

  • 步骤 1:字符串转数字(如 ASCII 求和:apple=97+112+112+108+101=530);

  • 步骤 2:m=10(哈希表大小);

  • 哈希地址:random(530) mod10=3random(627) mod10=7random(796) mod10=2 → 地址 {3,7,2}

3. 优缺点

优点 缺点
1. 分布均匀(随机数无规律,减少冲突);2. 适用于关键字分布极不规则的场景;3. 支持字符串、数字等多种关键字 1. 计算量较大(随机函数开销);2. 可重复性:同一关键字需生成同一地址(需固定随机种子);3. 查找时需重复计算随机数,效率略低

4. 适用场景

关键字分布极不规则(如随机生成的字符串、无规律的数字),或对冲突率要求极低的场景(如加密哈希的辅助构造)。

7.6 种方法对比与选择建议

构造方法 核心适用场景 冲突概率 实现复杂度 通用性
直接定址法 连续小范围数字关键字 无冲突 极简
数字分析法 长数字关键字(有均匀分布位) 中(需分析关键字) 中(仅数字)
平方取中法 短数字关键字(分布不规则) 中(仅数字)
折叠法 长数字 / 长字符串关键字
除留余数法 所有场景(数字 / 字符串) 中(依赖m 极简
随机数法 关键字分布极不规则 极低 中(需随机函数)

1.选择建议(优先级从高到低)

  1. 优先用除留余数法 :通用性强、实现简单,配合合理的 m(质数),冲突率可控制在较低水平(实际开发首选);

  2. 关键字是长数字(如身份证、手机号)→ 用数字分析法折叠法

  3. 关键字是连续小范围数字 → 用直接定址法(无冲突);

  4. 关键字分布极不规则 → 用随机数法(低冲突);

  5. 关键字是短数字(分布不规则)→ 用平方取中法

补充:字符串关键字的适配(6 种方法的扩展)

上述方法多针对数字关键字,若关键字是字符串(如 "apple""banana"),需先将字符串转为数字,再应用上述方法:

字符串转数字的 3 种常用方式

  1. ASCII 求和:"abc"97+98+99=294(简单但易冲突,如 "abc" 和 "cba" 求和相同);

  2. 多项式哈希:"abc"97×26² + 98×26 + 99= 97×676 + 98×26 + 99= 65572 + 2548 + 99= 68219(分布更均匀,减少冲突);

  3. 加权求和:"abc"97×3 + 98×2 + 99×1= 291 + 196 + 99= 586(自定义权重,灵活调整)。

示例:字符串 "apple" 用除留余数法构造哈希地址

  • 多项式哈希:a×26⁴ + p×26³ + p×26² + l×26 + e = 97×456976 + 112×17576 + 112×676 + 108×26 + 101 = 44326672 + 1968512 + 75712 + 2808 + 101 = 46373805

  • m=101(质数)→ H(key)=46373805 mod101= 46373805 - 101×459146= 46373805 - 46373746=59 → 地址 = 59。

总结

2.哈希函数的构造方法(6个)

2.1.直接定址法:对于关键字进行加减乘除法操作得其存储位置

原理:直接利用关键字本身或关键字的线性函数(如 f(key) = key + c、f(key) = a×key + b,其中 a、b、c 为常数)计算存储位置。

特点:简单直观,不会产生哈希冲突,但仅适用于关键字分布连续且范围较小的场景,否则会导致哈希表空间浪费。

示例:若学生学号范围是 1000~1099,可直接用 f(key) = key - 1000 将学号映射到 0~99 的存储位置。

2.2.数字分析法:属于较长的关键字,进行分析,找到其中的一部分作为关键字去使用

原理:针对关键字位数较长的情况,分析关键字各位的分布规律,选取分布均匀(即每位上数字出现概率相近)的若干位作为哈希地址。

特点:适用于已知关键字集合且分布规律明确的场景,能有效减少冲突。

示例:若关键字是身份证号(18 位),前 6 位为地址码(重复率高),后 4 位可能更分散,可选取后 4 位作为哈希地址。
2.3.平均取中法:数据较短,则先平法处理,再取其其中一部分

原理:将关键字平方后,取中间几位作为哈希地址(位数根据哈希表长度确定)。

特点:通过平方放大关键字的差异,使中间几位能较好地反映原关键字的特征,适用于关键字较短且分布不明显的场景。

示例:关键字为 123,平方后是 15129,若哈希表长度为 100(即需要 2 位地址),取中间两位 "12" 作为哈希地址。
2.4.折叠法:关键字较长,则切分后进行处理

原理:将长关键字按哈希表地址位数分成若干段,然后通过叠加(求和)或移位等方式合并这些段,得到哈希地址(若和超过地址范围,可对结果取模)

分类:移位折叠:将各段右对齐后相加(如关键字 12345678,分成 12、34、56、78,相加得 12 + 34 + 56 + 78 = 180)。

边界折叠:将奇数段右对齐、偶数段左对齐后相加(如 12、34、56、78 → 12 + 43 + 56 + 87 = 198)。

特点:适用于关键字较长且每段分布较均匀的场景,如电话号码、银行卡号等。

2.5.除留余数法 最常用的方法 f<key>=key mod p(p<m>)m是哈希表长度

原理:取关键字除以某个常数 p 的余数作为哈希地址,即 f(key) = key mod p,其中 p 通常取小于哈希表长度 m 的最大质数。

特点:简单高效,适用范围广,p 的选择对冲突率影响较大(p 为质数时冲突概率较低)。

示例:哈希表长度 m = 100,取 p = 97(小于 100 的最大质数),关键字 1234 的哈希地址为 1234 mod 97 = 1234 - 12×97 = 1234 - 1164 = 70。
2.6.随机数法

原理:选择一个随机函数,以关键字为参数生成随机数作为哈希地址,即 f(key) = random(key)。

特点:适用于关键字长度不固定或分布不规则的场景,随机性强,可减少冲突,但需保证相同关键字生成相同地址(即随机函数需是确定的)。

示例:对不同长度的字符串关键字,通过特定随机哈希算法(如 MurmurHash)生成固定长度的哈希值。

哈希函数构造的核心目标是 "地址分布均匀、冲突概率低、实现简单":

  • 实际开发中,除留余数法是首选(通用、简单、高效);

  • 特殊场景需结合关键字特征选择(如长数字用数字分析法,连续数字用直接定址法);

  • 无论选择哪种方法,都需配合冲突解决策略(开放定址法、链地址法),才能实现高效的哈希表查找。

相关推荐
散峰而望2 小时前
C++入门(算法) - 习题
开发语言·c++·算法·github
这张生成的图像能检测吗2 小时前
(论文速读)Regor - 渐进式对应点再生实现鲁棒3D配准
人工智能·算法·计算机视觉·配准·3d点云
leoufung3 小时前
贪心算法理论与应用——以股票买卖问题为例
算法·贪心算法
墨雪不会编程4 小时前
数据结构—排序算法篇三
数据结构·算法·排序算法
CoovallyAIHub4 小时前
外科医生离手术世界模型还有多远?首次提出SurgVeo基准,揭示AI生成手术视频的惊人差距
深度学习·算法·计算机视觉
t198751284 小时前
基于ELM算法在近红外光谱和拉曼光谱数据处理
算法
xqlily4 小时前
Prover9/Mace4 的形式化语言简介
人工智能·算法
资深web全栈开发4 小时前
二分搜索中 `right = mid` 而非 `right = mid + 1` 的解释
算法·rust·二分搜索