Translate all code to English (#1836)

* Review the EN heading format.

* Fix pythontutor headings.

* Fix pythontutor headings.

* bug fixes

* Fix headings in **/summary.md

* Revisit the CN-to-EN translation for Python code using Claude-4.5

* Revisit the CN-to-EN translation for Java code using Claude-4.5

* Revisit the CN-to-EN translation for Cpp code using Claude-4.5.

* Fix the dictionary.

* Fix cpp code translation for the multipart strings.

* Translate Go code to English.

* Update workflows to test EN code.

* Add EN translation for C.

* Add EN translation for CSharp.

* Add EN translation for Swift.

* Trigger the CI check.

* Revert.

* Update en/hash_map.md

* Add the EN version of Dart code.

* Add the EN version of Kotlin code.

* Add missing code files.

* Add the EN version of JavaScript code.

* Add the EN version of TypeScript code.

* Fix the workflows.

* Add the EN version of Ruby code.

* Add the EN version of Rust code.

* Update the CI check for the English version  code.

* Update Python CI check.

* Fix cmakelists for en/C code.

* Fix Ruby comments
This commit is contained in:
Yudong Jin
2025-12-31 07:44:52 +08:00
committed by GitHub
parent 45e1295241
commit 2778a6f9c7
1284 changed files with 71557 additions and 3275 deletions
+5 -5
View File
@@ -1,4 +1,4 @@
# Hash algorithm
# Hash Algorithm
The previous two sections introduced the working principle of hash tables and the methods to handle hash collisions. However, both open addressing and separate chaining **can only ensure that the hash table functions normally when hash collisions occur, but cannot reduce the frequency of hash collisions**.
@@ -16,7 +16,7 @@ Observing the above formula, when the hash table capacity `capacity` is fixed, *
This means that, to reduce the probability of hash collisions, we should focus on the design of the hash algorithm `hash()`.
## Goals of hash algorithms
## Goals of Hash Algorithms
To achieve a "fast and stable" hash table data structure, hash algorithms should have the following characteristics:
@@ -37,7 +37,7 @@ For cryptographic applications, to prevent reverse engineering such as deducing
Note that **"uniform distribution" and "collision resistance" are two independent concepts**. Satisfying uniform distribution does not necessarily mean collision resistance. For example, under random input `key`, the hash function `key % 100` can produce a uniformly distributed output. However, this hash algorithm is too simple, and all `key` with the same last two digits will have the same output, making it easy to deduce a usable `key` from the hash value, thereby cracking the password.
## Design of hash algorithms
## Design of Hash Algorithms
The design of hash algorithms is a complex issue that requires consideration of many factors. However, for some less demanding scenarios, we can also design some simple hash algorithms.
@@ -78,7 +78,7 @@ It is worth noting that if the `key` is guaranteed to be randomly and uniformly
In summary, we usually choose a prime number as the modulus, and this prime number should be large enough to eliminate periodic patterns as much as possible, enhancing the robustness of the hash algorithm.
## Common hash algorithms
## Common Hash Algorithms
It is not hard to see that the simple hash algorithms mentioned above are quite "fragile" and far from reaching the design goals of hash algorithms. For example, since addition and XOR obey the commutative law, additive hash and XOR hash cannot distinguish strings with the same content but in different order, which may exacerbate hash collisions and cause security issues.
@@ -100,7 +100,7 @@ Over the past century, hash algorithms have been in a continuous process of upgr
| Security Level | Low, has been successfully attacked | Low, has been successfully attacked | High | High |
| Applications | Abandoned, still used for data integrity checks | Abandoned | Cryptocurrency transaction verification, digital signatures, etc. | Can be used to replace SHA-2 |
# Hash values in data structures
# Hash Values in Data Structures
We know that the keys in a hash table can be of various data types such as integers, decimals, or strings. Programming languages usually provide built-in hash algorithms for these data types to calculate the bucket indices in the hash table. Taking Python as an example, we can use the `hash()` function to compute the hash values for various data types.
+7 -7
View File
@@ -1,4 +1,4 @@
# Hash collision
# Hash Collision
The previous section mentioned that, **in most cases, the input space of a hash function is much larger than the output space**, so theoretically, hash collisions are inevitable. For example, if the input space is all integers and the output space is the array capacity size, then multiple integers will inevitably be mapped to the same bucket index.
@@ -9,7 +9,7 @@ Hash collisions can lead to incorrect query results, severely impacting the usab
The main methods for improving the structure of hash tables include "separate chaining" and "open addressing".
## Separate chaining
## Separate Chaining
In the original hash table, each bucket can store only one key-value pair. <u>Separate chaining</u> converts a single element into a linked list, treating key-value pairs as linked list nodes and storing all colliding key-value pairs in the same linked list. The figure below shows an example of a separate chaining hash table.
@@ -37,13 +37,13 @@ The code below provides a simple implementation of a separate chaining hash tabl
It's worth noting that when the linked list is very long, the query efficiency $O(n)$ is poor. **In this case, the list can be converted to an "AVL tree" or "Red-Black tree"** to optimize the time complexity of the query operation to $O(\log n)$.
## Open addressing
## Open Addressing
<u>Open addressing</u> does not introduce additional data structures but instead handles hash collisions through "multiple probes". The probing methods mainly include linear probing, quadratic probing, and double hashing.
Let's use linear probing as an example to introduce the mechanism of open addressing hash tables.
### Linear probing
### Linear Probing
Linear probing uses a fixed-step linear search for probing, and its operation method differs from ordinary hash tables.
@@ -72,7 +72,7 @@ The code below implements an open addressing (linear probing) hash table with la
[file]{hash_map_open_addressing}-[class]{hash_map_open_addressing}-[func]{}
```
### Quadratic probing
### Quadratic Probing
Quadratic probing is similar to linear probing and is one of the common strategies for open addressing. When a collision occurs, quadratic probing does not simply skip a fixed number of steps but skips a number of steps equal to the "square of the number of probes", i.e., $1, 4, 9, \dots$ steps.
@@ -86,7 +86,7 @@ However, quadratic probing is not perfect:
- Clustering still exists, i.e., some positions are more likely to be occupied than others.
- Due to the growth of squares, quadratic probing may not probe the entire hash table, meaning that even if there are empty buckets in the hash table, quadratic probing may not be able to access them.
### Double hashing
### Double Hashing
As the name suggests, the double hashing method uses multiple hash functions $f_1(x)$, $f_2(x)$, $f_3(x)$, $\dots$ for probing.
@@ -99,7 +99,7 @@ Compared to linear probing, the double hashing method is less prone to clusterin
Please note that open addressing (linear probing, quadratic probing, and double hashing) hash tables all have the problem of "cannot directly delete elements".
## Choice of programming languages
## Choice of Programming Languages
Different programming languages adopt different hash table implementation strategies. Here are a few examples:
+64 -64
View File
@@ -1,4 +1,4 @@
# Hash table
# Hash Table
A <u>hash table</u>, also known as a <u>hash map</u>, establishes a mapping between keys `key` and values `value`, enabling efficient element retrieval. Specifically, when we input a key `key` into a hash table, we can retrieve the corresponding value `value` in $O(1)$ time.
@@ -22,7 +22,7 @@ In addition to hash tables, arrays and linked lists can also implement query fun
As observed, **the time complexity for insertion, deletion, search, and modification operations in a hash table is $O(1)$**, which is very efficient.
## Common hash table operations
## Common Hash Table Operations
Common operations on hash tables include: initialization, query operations, adding key-value pairs, and deleting key-value pairs. Example code is as follows:
@@ -34,11 +34,11 @@ Common operations on hash tables include: initialization, query operations, addi
# Add operation
# Add key-value pair (key, value) to hash table
hmap[12836] = "小哈"
hmap[15937] = "小啰"
hmap[16750] = "小算"
hmap[13276] = "小法"
hmap[10583] = "小鸭"
hmap[12836] = "XiaoHa"
hmap[15937] = "XiaoLuo"
hmap[16750] = "XiaoSuan"
hmap[13276] = "XiaoFa"
hmap[10583] = "XiaoYa"
# Query operation
# Input key into hash table to get value
@@ -57,11 +57,11 @@ Common operations on hash tables include: initialization, query operations, addi
/* Add operation */
// Add key-value pair (key, value) to hash table
map[12836] = "小哈";
map[15937] = "小啰";
map[16750] = "小算";
map[13276] = "小法";
map[10583] = "小鸭";
map[12836] = "XiaoHa";
map[15937] = "XiaoLuo";
map[16750] = "XiaoSuan";
map[13276] = "XiaoFa";
map[10583] = "XiaoYa";
/* Query operation */
// Input key into hash table to get value
@@ -80,11 +80,11 @@ Common operations on hash tables include: initialization, query operations, addi
/* Add operation */
// Add key-value pair (key, value) to hash table
map.put(12836, "小哈");
map.put(15937, "小啰");
map.put(16750, "小算");
map.put(13276, "小法");
map.put(10583, "小鸭");
map.put(12836, "XiaoHa");
map.put(15937, "XiaoLuo");
map.put(16750, "XiaoSuan");
map.put(13276, "XiaoFa");
map.put(10583, "XiaoYa");
/* Query operation */
// Input key into hash table to get value
@@ -102,11 +102,11 @@ Common operations on hash tables include: initialization, query operations, addi
Dictionary<int, string> map = new() {
/* Add operation */
// Add key-value pair (key, value) to hash table
{ 12836, "小哈" },
{ 15937, "小啰" },
{ 16750, "小算" },
{ 13276, "小法" },
{ 10583, "小鸭" }
{ 12836, "XiaoHa" },
{ 15937, "XiaoLuo" },
{ 16750, "XiaoSuan" },
{ 13276, "XiaoFa" },
{ 10583, "XiaoYa" }
};
/* Query operation */
@@ -126,11 +126,11 @@ Common operations on hash tables include: initialization, query operations, addi
/* Add operation */
// Add key-value pair (key, value) to hash table
hmap[12836] = "小哈"
hmap[15937] = "小啰"
hmap[16750] = "小算"
hmap[13276] = "小法"
hmap[10583] = "小鸭"
hmap[12836] = "XiaoHa"
hmap[15937] = "XiaoLuo"
hmap[16750] = "XiaoSuan"
hmap[13276] = "XiaoFa"
hmap[10583] = "XiaoYa"
/* Query operation */
// Input key into hash table to get value
@@ -149,11 +149,11 @@ Common operations on hash tables include: initialization, query operations, addi
/* Add operation */
// Add key-value pair (key, value) to hash table
map[12836] = "小哈"
map[15937] = "小啰"
map[16750] = "小算"
map[13276] = "小法"
map[10583] = "小鸭"
map[12836] = "XiaoHa"
map[15937] = "XiaoLuo"
map[16750] = "XiaoSuan"
map[13276] = "XiaoFa"
map[10583] = "XiaoYa"
/* Query operation */
// Input key into hash table to get value
@@ -171,11 +171,11 @@ Common operations on hash tables include: initialization, query operations, addi
const map = new Map();
/* Add operation */
// Add key-value pair (key, value) to hash table
map.set(12836, '小哈');
map.set(15937, '小啰');
map.set(16750, '小算');
map.set(13276, '小法');
map.set(10583, '小鸭');
map.set(12836, 'XiaoHa');
map.set(15937, 'XiaoLuo');
map.set(16750, 'XiaoSuan');
map.set(13276, 'XiaoFa');
map.set(10583, 'XiaoYa');
/* Query operation */
// Input key into hash table to get value
@@ -193,11 +193,11 @@ Common operations on hash tables include: initialization, query operations, addi
const map = new Map<number, string>();
/* Add operation */
// Add key-value pair (key, value) to hash table
map.set(12836, '小哈');
map.set(15937, '小啰');
map.set(16750, '小算');
map.set(13276, '小法');
map.set(10583, '小鸭');
map.set(12836, 'XiaoHa');
map.set(15937, 'XiaoLuo');
map.set(16750, 'XiaoSuan');
map.set(13276, 'XiaoFa');
map.set(10583, 'XiaoYa');
console.info('\nAfter adding, hash table is\nKey -> Value');
console.info(map);
@@ -221,11 +221,11 @@ Common operations on hash tables include: initialization, query operations, addi
/* Add operation */
// Add key-value pair (key, value) to hash table
map[12836] = "小哈";
map[15937] = "小啰";
map[16750] = "小算";
map[13276] = "小法";
map[10583] = "小鸭";
map[12836] = "XiaoHa";
map[15937] = "XiaoLuo";
map[16750] = "XiaoSuan";
map[13276] = "XiaoFa";
map[10583] = "XiaoYa";
/* Query operation */
// Input key into hash table to get value
@@ -246,11 +246,11 @@ Common operations on hash tables include: initialization, query operations, addi
/* Add operation */
// Add key-value pair (key, value) to hash table
map.insert(12836, "小哈".to_string());
map.insert(15937, "小啰".to_string());
map.insert(16750, "小算".to_string());
map.insert(13279, "小法".to_string());
map.insert(10583, "小鸭".to_string());
map.insert(12836, "XiaoHa".to_string());
map.insert(15937, "XiaoLuo".to_string());
map.insert(16750, "XiaoSuan".to_string());
map.insert(13279, "XiaoFa".to_string());
map.insert(10583, "XiaoYa".to_string());
/* Query operation */
// Input key into hash table to get value
@@ -275,11 +275,11 @@ Common operations on hash tables include: initialization, query operations, addi
/* Add operation */
// Add key-value pair (key, value) to hash table
map[12836] = "小哈"
map[15937] = "小啰"
map[16750] = "小算"
map[13276] = "小法"
map[10583] = "小鸭"
map[12836] = "XiaoHa"
map[15937] = "XiaoLuo"
map[16750] = "XiaoSuan"
map[13276] = "XiaoFa"
map[10583] = "XiaoYa"
/* Query operation */
// Input key into hash table to get value
@@ -298,11 +298,11 @@ Common operations on hash tables include: initialization, query operations, addi
# Add operation
# Add key-value pair (key, value) to hash table
hmap[12836] = "小哈"
hmap[15937] = "小啰"
hmap[16750] = "小算"
hmap[13276] = "小法"
hmap[10583] = "小鸭"
hmap[12836] = "XiaoHa"
hmap[15937] = "XiaoLuo"
hmap[16750] = "XiaoSuan"
hmap[13276] = "XiaoFa"
hmap[10583] = "XiaoYa"
# Query operation
# Input key into hash table to get value
@@ -550,7 +550,7 @@ There are three common ways to traverse a hash table: traversing key-value pairs
https://pythontutor.com/render.html#code=%22%22%22Driver%20Code%22%22%22%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20%23%20%E5%88%9D%E5%A7%8B%E5%8C%96%E5%93%88%E5%B8%8C%E8%A1%A8%0A%20%20%20%20hmap%20%3D%20%7B%7D%0A%20%20%20%20%0A%20%20%20%20%23%20%E6%B7%BB%E5%8A%A0%E6%93%8D%E4%BD%9C%0A%20%20%20%20%23%20%E5%9C%A8%E5%93%88%E5%B8%8C%E8%A1%A8%E4%B8%AD%E6%B7%BB%E5%8A%A0%E9%94%AE%E5%80%BC%E5%AF%B9%20%28key,%20value%29%0A%20%20%20%20hmap%5B12836%5D%20%3D%20%22%E5%B0%8F%E5%93%88%22%0A%20%20%20%20hmap%5B15937%5D%20%3D%20%22%E5%B0%8F%E5%95%B0%22%0A%20%20%20%20hmap%5B16750%5D%20%3D%20%22%E5%B0%8F%E7%AE%97%22%0A%20%20%20%20hmap%5B13276%5D%20%3D%20%22%E5%B0%8F%E6%B3%95%22%0A%20%20%20%20hmap%5B10583%5D%20%3D%20%22%E5%B0%8F%E9%B8%AD%22%0A%20%20%20%20%0A%20%20%20%20%23%20%E9%81%8D%E5%8E%86%E5%93%88%E5%B8%8C%E8%A1%A8%0A%20%20%20%20%23%20%E9%81%8D%E5%8E%86%E9%94%AE%E5%80%BC%E5%AF%B9%20key-%3Evalue%0A%20%20%20%20for%20key,%20value%20in%20hmap.items%28%29%3A%0A%20%20%20%20%20%20%20%20print%28key,%20%22-%3E%22,%20value%29%0A%20%20%20%20%23%20%E5%8D%95%E7%8B%AC%E9%81%8D%E5%8E%86%E9%94%AE%20key%0A%20%20%20%20for%20key%20in%20hmap.keys%28%29%3A%0A%20%20%20%20%20%20%20%20print%28key%29%0A%20%20%20%20%23%20%E5%8D%95%E7%8B%AC%E9%81%8D%E5%8E%86%E5%80%BC%20value%0A%20%20%20%20for%20value%20in%20hmap.values%28%29%3A%0A%20%20%20%20%20%20%20%20print%28value%29&cumulative=false&curInstr=8&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=311&rawInputLstJSON=%5B%5D&textReferences=false
## Simple hash table implementation
## Simple Hash Table Implementation
Let's first consider the simplest case: **implementing a hash table using only an array**. In a hash table, each empty position in the array is called a <u>bucket</u>, and each bucket can store a key-value pair. Therefore, the query operation is to find the bucket corresponding to `key` and retrieve the `value` from the bucket.
@@ -577,7 +577,7 @@ The following code implements a simple hash table. Here, we encapsulate `key` an
[file]{array_hash_map}-[class]{array_hash_map}-[func]{}
```
## Hash collision and resizing
## Hash Collision and Resizing
Fundamentally, the role of a hash function is to map the input space consisting of all `key`s to the output space consisting of all array indices, and the input space is often much larger than the output space. Therefore, **theoretically there must be cases where "multiple inputs correspond to the same output"**.
+1 -1
View File
@@ -1,6 +1,6 @@
# Summary
### Key review
### Key Review
- Given an input `key`, a hash table can retrieve the corresponding `value` in $O(1)$ time, which is highly efficient.
- Common hash table operations include querying, adding key-value pairs, deleting key-value pairs, and traversing the hash table.