mirror of
https://github.com/krahets/hello-algo.git
synced 2026-08-14 12:40:58 +00:00
build
This commit is contained in:
@@ -10,7 +10,7 @@ comments: true
|
||||
|
||||

|
||||
|
||||
<p align="center"> Fig. 哈希冲突的最佳与最差情况 </p>
|
||||
<p align="center"> 图:哈希冲突的最佳与最差情况 </p>
|
||||
|
||||
**键值对的分布情况由哈希函数决定**。回忆哈希函数的计算步骤,先计算哈希值,再对数组长度取模:
|
||||
|
||||
@@ -439,13 +439,45 @@ index = hash(key) % capacity
|
||||
=== "Dart"
|
||||
|
||||
```dart title="simple_hash.dart"
|
||||
[class]{}-[func]{add_hash}
|
||||
/* 加法哈希 */
|
||||
int addHash(String key) {
|
||||
int hash = 0;
|
||||
final int MODULUS = 1000000007;
|
||||
for (int i = 0; i < key.length; i++) {
|
||||
hash = (hash + key.codeUnitAt(i)) % MODULUS;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
[class]{}-[func]{mul_hash}
|
||||
/* 乘法哈希 */
|
||||
int mulHash(String key) {
|
||||
int hash = 0;
|
||||
final int MODULUS = 1000000007;
|
||||
for (int i = 0; i < key.length; i++) {
|
||||
hash = (31 * hash + key.codeUnitAt(i)) % MODULUS;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
[class]{}-[func]{xor_hash}
|
||||
/* 异或哈希 */
|
||||
int xorHash(String key) {
|
||||
int hash = 0;
|
||||
final int MODULUS = 1000000007;
|
||||
for (int i = 0; i < key.length; i++) {
|
||||
hash ^= key.codeUnitAt(i);
|
||||
}
|
||||
return hash & MODULUS;
|
||||
}
|
||||
|
||||
[class]{}-[func]{rot_hash}
|
||||
/* 旋转哈希 */
|
||||
int rotHash(String key) {
|
||||
int hash = 0;
|
||||
final int MODULUS = 1000000007;
|
||||
for (int i = 0; i < key.length; i++) {
|
||||
hash = ((hash << 4) ^ (hash >> 28) ^ key.codeUnitAt(i)) % MODULUS;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
```
|
||||
|
||||
=== "Rust"
|
||||
@@ -584,7 +616,7 @@ $$
|
||||
# 布尔量 True 的哈希值为 1
|
||||
|
||||
dec = 3.14159
|
||||
hash_dec = hash(dec)
|
||||
hash_dec = hash(dec)
|
||||
# 小数 3.14159 的哈希值为 326484311674566659
|
||||
|
||||
str = "Hello 算法"
|
||||
@@ -692,23 +724,23 @@ $$
|
||||
int num = 3;
|
||||
int hashNum = num.hashCode;
|
||||
// 整数 3 的哈希值为 34803
|
||||
|
||||
|
||||
bool bol = true;
|
||||
int hashBol = bol.hashCode;
|
||||
// 布尔值 true 的哈希值为 1231
|
||||
|
||||
|
||||
double dec = 3.14159;
|
||||
int hashDec = dec.hashCode;
|
||||
// 小数 3.14159 的哈希值为 2570631074981783
|
||||
|
||||
|
||||
String str = "Hello 算法";
|
||||
int hashStr = str.hashCode;
|
||||
// 字符串 Hello 算法 的哈希值为 468167534
|
||||
|
||||
|
||||
List arr = [12836, "小哈"];
|
||||
int hashArr = arr.hashCode;
|
||||
// 数组 [12836, 小哈] 的哈希值为 976512528
|
||||
|
||||
|
||||
ListNode obj = new ListNode(0);
|
||||
int hashObj = obj.hashCode;
|
||||
// 节点对象 Instance of 'ListNode' 的哈希值为 1033450432
|
||||
|
||||
@@ -19,7 +19,7 @@ comments: true
|
||||
|
||||

|
||||
|
||||
<p align="center"> Fig. 链式地址哈希表 </p>
|
||||
<p align="center"> 图:链式地址哈希表 </p>
|
||||
|
||||
链式地址下,哈希表的操作方法包括:
|
||||
|
||||
@@ -542,7 +542,7 @@ comments: true
|
||||
for (let i = 0; i < bucket.length; i++) {
|
||||
if (bucket[i].key === key) {
|
||||
bucket.splice(i, 1);
|
||||
this.size--;
|
||||
this.#size--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1165,7 +1165,7 @@ comments: true
|
||||
|
||||

|
||||
|
||||
<p align="center"> Fig. 线性探测 </p>
|
||||
<p align="center"> 图:线性探测 </p>
|
||||
|
||||
然而,线性探测存在以下缺陷:
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ comments: true
|
||||
|
||||

|
||||
|
||||
<p align="center"> Fig. 哈希表的抽象表示 </p>
|
||||
<p align="center"> 图:哈希表的抽象表示 </p>
|
||||
|
||||
除哈希表外,我们还可以使用数组或链表实现查询功能。若将学生数据看作数组(链表)元素,则有:
|
||||
|
||||
@@ -464,7 +464,7 @@ index = hash(key) % capacity
|
||||
|
||||

|
||||
|
||||
<p align="center"> Fig. 哈希函数工作原理 </p>
|
||||
<p align="center"> 图:哈希函数工作原理 </p>
|
||||
|
||||
以下代码实现了一个简单哈希表。其中,我们将 `key` 和 `value` 封装成一个类 `Pair` ,以表示键值对。
|
||||
|
||||
@@ -1501,13 +1501,13 @@ index = hash(key) % capacity
|
||||
|
||||

|
||||
|
||||
<p align="center"> Fig. 哈希冲突示例 </p>
|
||||
<p align="center"> 图:哈希冲突示例 </p>
|
||||
|
||||
容易想到,哈希表容量 $n$ 越大,多个 `key` 被分配到同一个桶中的概率就越低,冲突就越少。因此,**我们可以通过扩容哈希表来减少哈希冲突**。如下图所示,扩容前键值对 `(136, A)` 和 `(236, D)` 发生冲突,扩容后冲突消失。
|
||||
|
||||

|
||||
|
||||
<p align="center"> Fig. 哈希表扩容 </p>
|
||||
<p align="center"> 图:哈希表扩容 </p>
|
||||
|
||||
类似于数组扩容,哈希表扩容需将所有键值对从原哈希表迁移至新哈希表,非常耗时。并且由于哈希表容量 `capacity` 改变,我们需要通过哈希函数来重新计算所有键值对的存储位置,这进一步提高了扩容过程的计算开销。为此,编程语言通常会预留足够大的哈希表容量,防止频繁扩容。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user