# 📘 哈希函数的定义与作用


# ✅ 什么是哈希函数?

哈希函数是一个 将输入值映射到固定大小的输出空间 的函数。

  • 输入:任意数据(整数、字符串、对象等)

  • 输出:通常是一个固定范围的整数(例如 0 到 m−1m - 1m−1)

  • 记作:

    h : \mathcal{U} \rightarrow \

    其中 U 是输入的全集


# 🧰 用途 / 作用

哈希函数被用于实现:

应用说明
哈希表高效的数据结构,实现 dict / map
快速查找期望时间复杂度 O (1),比线性搜索快得多
数据分组把数据打散分配到不同桶中
数据去重用哈希值判断是否出现过
加密和校验如密码存储、完整性验证(SHA256 等)
图算法 / 流算法用哈希做随机划分、模拟、抽样(正是作业里的内容)

空间复杂度:O (logm + m'logm)


# 🔁 举例说明

例如,你要存储学生姓名 "Alice" ,你可以使用:

row
1
2
3
def hash(name):
return sum(ord(c) for c in name) % 100

  • 这样 "Alice" → 哈希值在 0~99 之间

  • 存在哈希表中时,就可以根据哈希值快速定位到对应的位置


# ❓为什么我们需要哈希函数?

因为我们希望:

  • 快速插入、查找、删除数据(比数组快)

  • 分布要尽量 “均匀”,避免太多冲突

  • 在算法中模拟 “随机分组”“颜色划分” 等操作(例如 MaxCut)

# 一些自己的理解

所谓哈希表,就是底层使用哈希函数来实现的表
例如 dic,他的本质就是比如将一个名为 'David' 的数据,通过哈希函数加密,例如 hash ('David') = 17,那么将直接去寻找地址为 17 的位置的值,故哈希表的查询非常快,因为他只需要通过哈希函数就可以直接查找到目标位置,而不需要遍历。
如 set,就是通过哈希值的形式实现查重和去重。

# 🎯 主旨:哈希表遇到 “哈希冲突” 怎么办?

# 所谓哈希冲突是指:

两个不同的输入,通过哈希函数后,得到相同的哈希值(= 同一个位置)


# 🧱 哈希表内部的数据结构

哈希表背后是一个 “数组”,哈希函数输出的是数组的下标。

比如:

row
1
2
"Apple"hash3
"Banana"hash3 (冲突!)

# 🔨 如何解决冲突(重点)

# 方法一:Separate Chaining(链地址法)

  • 每个位置放一个链表(或列表)

  • 所有落在同一位置的元素,都挂在那一桶后面

  • 就像 “一个抽屉里放多个文件”

🧠 优点:结构简单,易实现
📉 缺点:查找慢时可能退化为链表查找 O (n)


# 方法二:Open Addressing(开放寻址法)

  • 如果位置被占了,就往后找一个空位

  • 所有元素都存在主数组中,不用额外链表


# 🔹 线性探测(Linear Probing)
  • 冲突时,往后挨个找空位:
    row
    1
    hash("Apple") = 3 → 位置 3 被占 → 试 4 → 再试 5 ...

    🧠 优点:实现简单
    📉 缺点:容易形成 “堆积效应”(连续位置都被占)
# 🔹 布谷鸟哈希(Cuckoo Hashing)
  • 使用 多个哈希函数(比如两个)

  • 每个元素可以存在两个位置之一

  • 如果都被占,就踢出原来的值,重新放

🧠 类似布谷鸟把别人蛋踢出去放自己的蛋
📈 性能优秀,查找是常数时间 O (1)


# ✅ 总结对你有用的理解:

方法原理类比
Separate Chaining同位置挂链表一个格子放多个书签
Open Addressing冲突时换地方柜子满了换下一个抽屉
Linear Probing一格一格往后找
Cuckoo Hashing多位置可放,挤出旧的布谷鸟占窝蛋 🐣

# 3. 随机性在哈希函数中的作用

  • 在理论上,很多分析都会假设哈希函数是完全随机的

  • 但在实际中,我们不能真地做到这一点(因为完全随机函数是无限大、不可实现的)

  • 所以我们用的是 “哈希函数族”,例如:

    • 2-universal(两两独立的哈希函数族)

    • k-wise independent(k - 元独立哈希函数族)

✔️ 所以我们希望找到一种 简单、可实现、但表现类似完全随机 的哈希函数。

# ✅ 1. 理论 vs 实践:完全随机 vs 可实现哈希函数

  • 在很多算法分析中(比如概率分析),我们常常假设哈希函数是 “完全随机” 的,也叫做:

    理想哈希函数,它对每个输入输出完全独立均匀分布。

    但问题是:你没法真正实现一个完美随机函数,因为它需要无限多的随机比特。


# ✅ 2. 所以我们做了什么?—— 构造 “哈希函数族”

我们定义一族函数 H={h1,h2,...,hn}\mathcal{H} = \{ h_1, h_2, ..., h_n \} ,从中随机挑一个函数来用。

这叫做:

哈希函数族(hash function family)

而且我们希望这个族具备一些 “随机性保证”:


# 🔹 常见的哈希函数族类型

类型含义示例
2-universal (两两独立)对任意不同输入 x≠yx \neq yx=y,哈希值 h (x),h (y) h (x), h (y) h (x),h (y) 是独立的你作业中实现的就是这个
k-wise independent任意 kkk 个输入的哈希值是联合独立的更强,适合更高级算法

# 🔸 举个你熟悉的例子(你作业中):

ha,b(x)=((ax+b)modp)mod2h_{a,b}(x) = ((a \cdot x + b) \mod p) \mod 2

这个就构成了一个 2-universal 的哈希函数族!

# 🔹 Pairwise Independent Hash Functions(两两独立)


哈希族 H 是两两独立的,当对任意 x≠y:

PrhH[h(x)=ih(y)=j]=Pr[h(x)=i]Pr[h(y)=j]\Pr_{h \in \mathcal{H}}[h(x) = i \land h(y) = j] = \Pr[h(x) = i] \cdot \Pr[h(y) = j]

这个公式的意思是:

对于任何两个不同的输入 x 和 y,它们的哈希结果是独立分布

也就是说:

  • h (x) 的结果不会影响 h (y) 的结果

  • 就像真的从完全随机函数中取出来一样(虽然我们只是从一个 “函数族” 中选)


# 🔧 为什么叫 “2-universal” 或 “两两独立”?

  • 是指:只要求任意两个输入之间的结果是独立的(不要求 3 个或更多输入联合独立)

  • 比起完全独立(所有输入都独立),更容易实现,但仍有强大理论保证


# ✅ 第三行:

举了经典构造:

ha,b(x)=((ax+b)modp)modmh_{a,b}(x) = ((a \cdot x + b) \mod p) \mod m

这个就是你在作业中要用的哈希函数形式!

  • p:一个大于输入范围的素数

  • m:哈希输出范围(比如你要输出 0 或 1 就设 m=2m = 2m=2)

  • a,b{0,1,...,p1}a, b \in \{0, 1, ..., p-1\},** 但要求 a≠0


# ✅ 这个构造的厉害之处?

数学证明:这个哈希函数族是两两独立的
即你随便选两个不同的输入 x≠y,它们的哈希值是独立的!


# 🧪 举个简单例子:

设:

  • p=101(素数)

  • m=2(你想要一个 0 或 1 的哈希值)

  • 随机选 a=7, b=13

那:

h(x)=((7x+13)mod101)mod2h(x) = ((7 \cdot x + 13) \mod 101) \mod 2

  • 对 x=3,哈希值可能是 1

  • 对 x=5,哈希值可能是 0
    并且这两个结果是概率独立的


# ✅ 总结一句话:

你作业中实现的 h(n, r, x) 就是在构造一个两两独立哈希函数族中的成员,用它来保证哈希结果足够随机但可控,用于各种概率算法(比如 MaxCut 随机分组)。

# 5. 应用拓展:布隆过滤器、流处理、数据结构

这是讲哈希函数在实际算法与系统设计中的应用场景。具体包括:


# ✅ 1. 布隆过滤器(Bloom Filters)

  • 是一种节省空间的集合判断结构

  • 可以快速判断一个元素是否 “可能存在” 于集合中

  • 使用 多个哈希函数 映射到一个位数组中

# 🔍 特点:

优点缺点
空间非常省会有 “假阳性”:可能说存在但其实没有
查询非常快不支持删除元素(除非用 Counting Bloom Filter)

典型用途:网页缓存、数据库、网络黑名单、区块链去重等


# ✅ 2. 哈希在流处理算法中的应用

比如在处理大规模数据流时(比如网络数据包、日志流):

  • 无法保存全部数据

  • 但你可以用哈希函数来做:

    • 估计不同元素个数(distinct counting)

    • 检测频繁项(heavy hitters)

    • 滑动窗口统计

这些技术都用到了类似 “哈希函数族 + 位数组 / 计数器” 的结构。


# ✅ 3. 哈希函数在其他数据结构中的应用

例如:

  • Skip lists(跳表):部分使用哈希构造跳跃层

  • Count-Min Sketch(用于频率估计)

  • HyperLogLog(用于基数估计)

  • Cuckoo Hashing(你刚学的!)


# ✅ 4. 引用的论文:Mitzenmacher & Vadhan, 2008

这句话说的是:

虽然我们在理论中用的是 “完全随机” 的哈希函数,
但实践中即使用简单的哈希函数族(比如两两独立),实际效果也很好

这也是你课程强调的重点之一:

我们不需要 “完美随机”,只要够用的随机性 + 理论保证 → 依然很强!


# ✅ 总结一句话:

这一部分告诉你:哈希函数不仅是基础结构,更是很多现代算法和系统的关键组成部分。从节省空间到流式处理,哈希的 “轻量 + 随机 + 快速” 特性,使它成为构建高效系统的利器。

更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

IRON 微信支付

微信支付

IRON 支付宝

支付宝

IRON 贝宝

贝宝