2023-02-16 03:39:01 +08:00
|
|
|
|
# 哈希查找
|
2022-11-22 17:47:26 +08:00
|
|
|
|
|
2023-04-10 03:11:49 +08:00
|
|
|
|
「哈希查找 Hash Searching」通过使用哈希表来存储所需的键值对,从而可在 $O(1)$ 时间内完成“键 $\rightarrow$ 值”的查找操作。
|
2022-11-22 17:47:26 +08:00
|
|
|
|
|
2023-04-10 03:11:49 +08:00
|
|
|
|
与线性查找相比,哈希查找通过利用额外空间来提高效率,体现了“以空间换时间”的算法思想。
|
2022-11-22 17:47:26 +08:00
|
|
|
|
|
2023-02-16 03:39:01 +08:00
|
|
|
|
## 算法实现
|
2022-11-22 17:47:26 +08:00
|
|
|
|
|
2023-04-10 03:11:49 +08:00
|
|
|
|
例如,若我们想要在给定数组中找到目标元素 `target` 的索引,则可以使用哈希查找来实现。
|
2022-11-22 17:47:26 +08:00
|
|
|
|
|
2023-02-26 18:18:34 +08:00
|
|
|
|
![哈希查找数组索引](hashing_search.assets/hash_search_index.png)
|
2022-11-22 17:47:26 +08:00
|
|
|
|
|
|
|
|
|
=== "Java"
|
|
|
|
|
|
|
|
|
|
```java title="hashing_search.java"
|
2023-02-07 04:43:52 +08:00
|
|
|
|
[class]{hashing_search}-[func]{hashingSearchArray}
|
2022-11-22 17:47:26 +08:00
|
|
|
|
```
|
|
|
|
|
|
2022-11-27 04:20:30 +08:00
|
|
|
|
=== "C++"
|
|
|
|
|
|
|
|
|
|
```cpp title="hashing_search.cpp"
|
2023-02-08 04:17:26 +08:00
|
|
|
|
[class]{}-[func]{hashingSearchArray}
|
2022-11-27 04:20:30 +08:00
|
|
|
|
```
|
|
|
|
|
|
2022-12-03 01:31:29 +08:00
|
|
|
|
=== "Python"
|
|
|
|
|
|
|
|
|
|
```python title="hashing_search.py"
|
2023-02-06 23:23:21 +08:00
|
|
|
|
[class]{}-[func]{hashing_search_array}
|
2022-12-03 01:31:29 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
=== "Go"
|
|
|
|
|
|
|
|
|
|
```go title="hashing_search.go"
|
2023-02-09 04:45:06 +08:00
|
|
|
|
[class]{}-[func]{hashingSearchArray}
|
2022-12-03 01:31:29 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
=== "JavaScript"
|
|
|
|
|
|
2023-02-08 04:27:55 +08:00
|
|
|
|
```javascript title="hashing_search.js"
|
2023-02-08 19:45:06 +08:00
|
|
|
|
[class]{}-[func]{hashingSearchArray}
|
2022-12-03 01:31:29 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
=== "TypeScript"
|
|
|
|
|
|
|
|
|
|
```typescript title="hashing_search.ts"
|
2023-02-08 19:45:06 +08:00
|
|
|
|
[class]{}-[func]{hashingSearchArray}
|
2022-12-03 01:31:29 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
=== "C"
|
|
|
|
|
|
|
|
|
|
```c title="hashing_search.c"
|
2023-02-11 18:22:27 +08:00
|
|
|
|
[class]{}-[func]{hashingSearchArray}
|
2022-12-03 01:31:29 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
=== "C#"
|
|
|
|
|
|
|
|
|
|
```csharp title="hashing_search.cs"
|
2023-02-08 22:18:02 +08:00
|
|
|
|
[class]{hashing_search}-[func]{hashingSearchArray}
|
2022-12-03 01:31:29 +08:00
|
|
|
|
```
|
|
|
|
|
|
2023-01-08 19:41:05 +08:00
|
|
|
|
=== "Swift"
|
|
|
|
|
|
|
|
|
|
```swift title="hashing_search.swift"
|
2023-02-08 20:30:05 +08:00
|
|
|
|
[class]{}-[func]{hashingSearchArray}
|
2023-01-08 19:41:05 +08:00
|
|
|
|
```
|
|
|
|
|
|
2023-02-01 22:03:04 +08:00
|
|
|
|
=== "Zig"
|
|
|
|
|
|
|
|
|
|
```zig title="hashing_search.zig"
|
2023-02-09 22:57:25 +08:00
|
|
|
|
[class]{}-[func]{hashingSearchArray}
|
2023-02-01 22:03:04 +08:00
|
|
|
|
```
|
|
|
|
|
|
2023-04-10 03:11:49 +08:00
|
|
|
|
同样,若要根据目标节点值 target 查找对应的链表节点对象,也可以采用哈希查找方法。
|
2022-11-22 17:47:26 +08:00
|
|
|
|
|
2023-04-09 04:32:17 +08:00
|
|
|
|
![哈希查找链表节点](hashing_search.assets/hash_search_listnode.png)
|
2022-11-22 17:47:26 +08:00
|
|
|
|
|
|
|
|
|
=== "Java"
|
|
|
|
|
|
|
|
|
|
```java title="hashing_search.java"
|
2023-02-07 04:43:52 +08:00
|
|
|
|
[class]{hashing_search}-[func]{hashingSearchLinkedList}
|
2022-11-22 17:47:26 +08:00
|
|
|
|
```
|
|
|
|
|
|
2022-11-27 04:20:30 +08:00
|
|
|
|
=== "C++"
|
|
|
|
|
|
|
|
|
|
```cpp title="hashing_search.cpp"
|
2023-02-08 04:17:26 +08:00
|
|
|
|
[class]{}-[func]{hashingSearchLinkedList}
|
2022-11-27 04:20:30 +08:00
|
|
|
|
```
|
|
|
|
|
|
2022-12-03 01:31:29 +08:00
|
|
|
|
=== "Python"
|
|
|
|
|
|
|
|
|
|
```python title="hashing_search.py"
|
2023-02-06 23:23:21 +08:00
|
|
|
|
[class]{}-[func]{hashing_search_linkedlist}
|
2022-12-03 01:31:29 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
=== "Go"
|
|
|
|
|
|
|
|
|
|
```go title="hashing_search.go"
|
2023-02-09 04:45:06 +08:00
|
|
|
|
[class]{}-[func]{hashingSearchLinkedList}
|
2022-12-03 01:31:29 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
=== "JavaScript"
|
|
|
|
|
|
2023-02-08 04:27:55 +08:00
|
|
|
|
```javascript title="hashing_search.js"
|
2023-02-08 19:45:06 +08:00
|
|
|
|
[class]{}-[func]{hashingSearchLinkedList}
|
2022-12-03 01:31:29 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
=== "TypeScript"
|
|
|
|
|
|
|
|
|
|
```typescript title="hashing_search.ts"
|
2023-02-08 19:45:06 +08:00
|
|
|
|
[class]{}-[func]{hashingSearchLinkedList}
|
2022-12-03 01:31:29 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
=== "C"
|
|
|
|
|
|
|
|
|
|
```c title="hashing_search.c"
|
2023-02-11 18:22:27 +08:00
|
|
|
|
[class]{}-[func]{hashingSearchLinkedList}
|
2022-12-03 01:31:29 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
=== "C#"
|
|
|
|
|
|
|
|
|
|
```csharp title="hashing_search.cs"
|
2023-02-08 22:18:02 +08:00
|
|
|
|
[class]{hashing_search}-[func]{hashingSearchLinkedList}
|
2022-12-03 01:31:29 +08:00
|
|
|
|
```
|
|
|
|
|
|
2023-01-08 19:41:05 +08:00
|
|
|
|
=== "Swift"
|
|
|
|
|
|
|
|
|
|
```swift title="hashing_search.swift"
|
2023-02-08 20:30:05 +08:00
|
|
|
|
[class]{}-[func]{hashingSearchLinkedList}
|
2023-01-08 19:41:05 +08:00
|
|
|
|
```
|
|
|
|
|
|
2023-02-01 22:03:04 +08:00
|
|
|
|
=== "Zig"
|
|
|
|
|
|
|
|
|
|
```zig title="hashing_search.zig"
|
2023-02-09 22:57:25 +08:00
|
|
|
|
[class]{}-[func]{hashingSearchLinkedList}
|
2023-02-01 22:03:04 +08:00
|
|
|
|
```
|
|
|
|
|
|
2023-02-16 03:39:01 +08:00
|
|
|
|
## 复杂度分析
|
2022-11-22 17:47:26 +08:00
|
|
|
|
|
2023-01-09 22:39:30 +08:00
|
|
|
|
**时间复杂度 $O(1)$** :哈希表的查找操作使用 $O(1)$ 时间。
|
2022-11-22 17:47:26 +08:00
|
|
|
|
|
2023-04-10 03:11:49 +08:00
|
|
|
|
**空间复杂度 $O(n)$** :其中 $n$ 是数组或链表的长度。
|
2022-11-22 17:47:26 +08:00
|
|
|
|
|
2023-04-10 03:11:49 +08:00
|
|
|
|
## 优点与局限性
|
2022-11-22 17:47:26 +08:00
|
|
|
|
|
2023-04-10 03:11:49 +08:00
|
|
|
|
哈希查找的性能表现相当优秀,查找、插入、删除操作的平均时间复杂度均为 $O(1)$ 。尽管如此,哈希查找仍然存在一些问题:
|
2022-11-22 17:47:26 +08:00
|
|
|
|
|
2023-04-10 03:11:49 +08:00
|
|
|
|
- 辅助哈希表需要占用 $O(n)$ 的额外空间,意味着需要预留更多的计算机内存;
|
|
|
|
|
- 构建和维护哈希表需要时间,因此哈希查找不适用于高频增删、低频查找的场景;
|
|
|
|
|
- 当哈希冲突严重时,哈希表可能退化为链表,导致时间复杂度劣化至 $O(n)$ ;
|
|
|
|
|
- 当数据量较小时,线性查找可能比哈希查找更快。这是因为计算哈希函数可能比遍历一个小型数组更慢;
|
2022-11-22 17:47:26 +08:00
|
|
|
|
|
2023-04-10 03:11:49 +08:00
|
|
|
|
因此,在实际应用中,我们需要根据具体情况灵活选择解决方案。
|