mirror of
https://github.com/krahets/hello-algo.git
synced 2026-07-17 01:06:07 +00:00
build
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
comments: true
|
||||
---
|
||||
|
||||
# 6.3. 哈希算法
|
||||
# 6.3 哈希算法
|
||||
|
||||
在上两节中,我们了解了哈希表的工作原理和哈希冲突的处理方法。然而无论是开放寻址还是链地址法,**它们只能保证哈希表可以在发生冲突时正常工作,但无法减少哈希冲突的发生**。
|
||||
|
||||
@@ -22,7 +22,7 @@ index = hash(key) % capacity
|
||||
|
||||
这意味着,为了减小哈希冲突的发生概率,我们应当将注意力集中在哈希算法 `hash()` 的设计上。
|
||||
|
||||
## 6.3.1. 哈希算法的目标
|
||||
## 6.3.1 哈希算法的目标
|
||||
|
||||
为了实现“既快又稳”的哈希表数据结构,哈希算法应包含以下特点:
|
||||
|
||||
@@ -42,7 +42,7 @@ index = hash(key) % capacity
|
||||
|
||||
请注意,**“均匀分布”与“抗碰撞性”是两个独立的概念**,满足均匀分布不一定满足抗碰撞性。例如,在随机输入 `key` 下,哈希函数 `key % 100` 可以产生均匀分布的输出。然而该哈希算法过于简单,所有后两位相等的 `key` 的输出都相同,因此我们可以很容易地从哈希值反推出可用的 `key` ,从而破解密码。
|
||||
|
||||
## 6.3.2. 哈希算法的设计
|
||||
## 6.3.2 哈希算法的设计
|
||||
|
||||
哈希算法的设计是一个复杂且需要考虑许多因素的问题。然而对于简单场景,我们也能设计一些简单的哈希算法。以字符串哈希为例:
|
||||
|
||||
@@ -520,7 +520,7 @@ $$
|
||||
|
||||
总而言之,我们通常选取质数作为模数,并且这个质数最好足够大,以尽可能消除周期性模式,提升哈希算法的稳健性。
|
||||
|
||||
## 6.3.3. 常见哈希算法
|
||||
## 6.3.3 常见哈希算法
|
||||
|
||||
不难发现,以上介绍的简单哈希算法都比较“脆弱”,远远没有达到哈希算法的设计目标。例如,由于加法和异或满足交换律,因此加法哈希和异或哈希无法区分内容相同但顺序不同的字符串,这可能会加剧哈希冲突,并引起一些安全问题。
|
||||
|
||||
@@ -544,7 +544,7 @@ $$
|
||||
|
||||
</div>
|
||||
|
||||
## 6.3.4. 数据结构的哈希值
|
||||
## 6.3.4 数据结构的哈希值
|
||||
|
||||
我们知道,哈希表的 `key` 可以是整数、小数或字符串等数据类型。编程语言通常会为这些数据类型提供内置的哈希算法,用于计算哈希表中的桶索引。以 Python 为例,我们可以调用 `hash()` 函数来计算各种数据类型的哈希值,包括:
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
comments: true
|
||||
---
|
||||
|
||||
# 6.2. 哈希冲突
|
||||
# 6.2 哈希冲突
|
||||
|
||||
上节提到,**通常情况下哈希函数的输入空间远大于输出空间**,因此理论上哈希冲突是不可避免的。比如,输入空间为全体整数,输出空间为数组容量大小,则必然有多个整数映射至同一数组索引。
|
||||
|
||||
@@ -13,7 +13,7 @@ comments: true
|
||||
|
||||
哈希表的结构改良方法主要包括链式地址和开放寻址。
|
||||
|
||||
## 6.2.1. 链式地址
|
||||
## 6.2.1 链式地址
|
||||
|
||||
在原始哈希表中,每个桶仅能存储一个键值对。「链式地址 Separate Chaining」将单个元素转换为链表,将键值对作为链表节点,将所有发生冲突的键值对都存储在同一链表中。
|
||||
|
||||
@@ -1152,7 +1152,7 @@ comments: true
|
||||
|
||||
当链表很长时,查询效率 $O(n)$ 很差,**此时可以将链表转换为「AVL 树」或「红黑树」**,从而将查询操作的时间复杂度优化至 $O(\log n)$ 。
|
||||
|
||||
## 6.2.2. 开放寻址
|
||||
## 6.2.2 开放寻址
|
||||
|
||||
「开放寻址 Open Addressing」不引入额外的数据结构,而是通过“多次探测”来处理哈希冲突,探测方式主要包括线性探测、平方探测、多次哈希等。
|
||||
|
||||
@@ -2448,7 +2448,7 @@ comments: true
|
||||
|
||||
与线性探测相比,多次哈希方法不易产生聚集,但多个哈希函数会增加额外的计算量。
|
||||
|
||||
## 6.2.3. 编程语言的选择
|
||||
## 6.2.3 编程语言的选择
|
||||
|
||||
Java 采用链式地址。自 JDK 1.8 以来,当 HashMap 内数组长度达到 64 且链表长度达到 8 时,链表会被转换为红黑树以提升查找性能。
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
comments: true
|
||||
---
|
||||
|
||||
# 6.1. 哈希表
|
||||
# 6.1 哈希表
|
||||
|
||||
散列表,又称「哈希表 Hash Table」,其通过建立键 `key` 与值 `value` 之间的映射,实现高效的元素查询。具体而言,我们向哈希表输入一个键 `key` ,则可以在 $O(1)$ 时间内获取对应的值 `value` 。
|
||||
|
||||
@@ -31,7 +31,7 @@ comments: true
|
||||
|
||||
观察发现,**在哈希表中进行增删查改的时间复杂度都是 $O(1)$** ,非常高效。
|
||||
|
||||
## 6.1.1. 哈希表常用操作
|
||||
## 6.1.1 哈希表常用操作
|
||||
|
||||
哈希表的常见操作包括:初始化、查询操作、添加键值对和删除键值对等。
|
||||
|
||||
@@ -444,7 +444,7 @@ comments: true
|
||||
|
||||
```
|
||||
|
||||
## 6.1.2. 哈希表简单实现
|
||||
## 6.1.2 哈希表简单实现
|
||||
|
||||
我们先考虑最简单的情况,**仅用一个数组来实现哈希表**。在哈希表中,我们将数组中的每个空位称为「桶 Bucket」,每个桶可存储一个键值对。因此,查询操作就是找到 `key` 对应的桶,并在桶中获取 `value` 。
|
||||
|
||||
@@ -1487,7 +1487,7 @@ index = hash(key) % capacity
|
||||
}
|
||||
```
|
||||
|
||||
## 6.1.3. 哈希冲突与扩容
|
||||
## 6.1.3 哈希冲突与扩容
|
||||
|
||||
本质上看,哈希函数的作用是将所有 `key` 构成的输入空间映射到数组所有索引构成的输出空间,而输入空间往往远大于输出空间。因此,**理论上一定存在“多个输入对应相同输出”的情况**。
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ comments: true
|
||||
icon: material/table-search
|
||||
---
|
||||
|
||||
# 6. 散列表
|
||||
# 第 6 章 散列表
|
||||
|
||||
<div class="center-table" markdown>
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
comments: true
|
||||
---
|
||||
|
||||
# 6.4. 小结
|
||||
# 6.4 小结
|
||||
|
||||
- 输入 `key` ,哈希表能够在 $O(1)$ 时间内查询到 `value` ,效率非常高。
|
||||
- 常见的哈希表操作包括查询、添加键值对、删除键值对和遍历哈希表等。
|
||||
@@ -18,7 +18,7 @@ comments: true
|
||||
- 常见的哈希算法包括 MD5, SHA-1, SHA-2, SHA3 等。MD5 常用于校验文件完整性,SHA-2 常用于安全应用与协议。
|
||||
- 编程语言通常会为数据类型提供内置哈希算法,用于计算哈希表中的桶索引。通常情况下,只有不可变对象是可哈希的。
|
||||
|
||||
## 6.4.1. Q & A
|
||||
## 6.4.1 Q & A
|
||||
|
||||
!!! question "哈希表的时间复杂度为什么不是 $O(n)$ ?"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user