From 0bd4c34b9aba274f0368d05d82b48debf3de93eb Mon Sep 17 00:00:00 2001 From: Yudong Jin Date: Sun, 28 Jan 2024 22:22:36 +0800 Subject: [PATCH] translation: Add the initial translation of the hashing chapter (#1066) * Add the initial translation of the hashing chapter * Fix --- .../hash_collision_best_worst_condition.png | Bin 0 -> 26326 bytes docs-en/chapter_hashing/hash_algorithm.md | 360 ++++++++++++ .../hash_table_chaining.png | Bin 0 -> 30209 bytes .../hash_table_linear_probing.png | Bin 0 -> 20486 bytes .../hash_table_open_addressing_deletion.png | Bin 0 -> 17523 bytes docs-en/chapter_hashing/hash_collision.md | 108 ++++ .../hash_map.assets/hash_collision.png | Bin 0 -> 30765 bytes .../hash_map.assets/hash_function.png | Bin 0 -> 33971 bytes .../hash_map.assets/hash_table_lookup.png | Bin 0 -> 18323 bytes .../hash_map.assets/hash_table_reshash.png | Bin 0 -> 27971 bytes docs-en/chapter_hashing/hash_map.md | 525 ++++++++++++++++++ docs-en/chapter_hashing/index.md | 13 + docs-en/chapter_hashing/summary.md | 47 ++ docs-en/chapter_stack_and_queue/deque.md | 2 +- docs-en/chapter_stack_and_queue/queue.md | 2 +- docs-en/chapter_stack_and_queue/stack.md | 2 +- docs/chapter_hashing/hash_algorithm.md | 1 - mkdocs-en.yml | 14 +- 18 files changed, 1063 insertions(+), 11 deletions(-) create mode 100644 docs-en/chapter_hashing/hash_algorithm.assets/hash_collision_best_worst_condition.png create mode 100644 docs-en/chapter_hashing/hash_algorithm.md create mode 100644 docs-en/chapter_hashing/hash_collision.assets/hash_table_chaining.png create mode 100644 docs-en/chapter_hashing/hash_collision.assets/hash_table_linear_probing.png create mode 100644 docs-en/chapter_hashing/hash_collision.assets/hash_table_open_addressing_deletion.png create mode 100644 docs-en/chapter_hashing/hash_collision.md create mode 100644 docs-en/chapter_hashing/hash_map.assets/hash_collision.png create mode 100644 docs-en/chapter_hashing/hash_map.assets/hash_function.png create mode 100644 docs-en/chapter_hashing/hash_map.assets/hash_table_lookup.png create mode 100644 docs-en/chapter_hashing/hash_map.assets/hash_table_reshash.png create mode 100755 docs-en/chapter_hashing/hash_map.md create mode 100644 docs-en/chapter_hashing/index.md create mode 100644 docs-en/chapter_hashing/summary.md diff --git a/docs-en/chapter_hashing/hash_algorithm.assets/hash_collision_best_worst_condition.png b/docs-en/chapter_hashing/hash_algorithm.assets/hash_collision_best_worst_condition.png new file mode 100644 index 0000000000000000000000000000000000000000..91a47d0ae641a954682ca8f5895bf1b05419f4cd GIT binary patch literal 26326 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 literal 0 HcmV?d00001 diff --git a/docs-en/chapter_hashing/hash_algorithm.md b/docs-en/chapter_hashing/hash_algorithm.md new file mode 100644 index 000000000..fa57e4a66 --- /dev/null +++ b/docs-en/chapter_hashing/hash_algorithm.md @@ -0,0 +1,360 @@ +# Hash Algorithms + +The previous two sections introduced the working principle of hash tables and the methods to handle hash collisions. However, both open addressing and chaining can **only ensure that the hash table functions normally when collisions occur, but cannot reduce the frequency of hash collisions**. + +If hash collisions occur too frequently, the performance of the hash table will deteriorate drastically. As shown in the figure below, for a chaining hash table, in the ideal case, the key-value pairs are evenly distributed across the buckets, achieving optimal query efficiency; in the worst case, all key-value pairs are stored in the same bucket, degrading the time complexity to $O(n)$. + +![Ideal and Worst Cases of Hash Collisions](hash_algorithm.assets/hash_collision_best_worst_condition.png) + +**The distribution of key-value pairs is determined by the hash function**. Recalling the steps of calculating a hash function, first compute the hash value, then modulo it by the array length: + +```shell +index = hash(key) % capacity +``` + +Observing the above formula, when the hash table capacity `capacity` is fixed, **the hash algorithm `hash()` determines the output value**, thereby determining the distribution of key-value pairs in the hash table. + +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 + +To achieve a "fast and stable" hash table data structure, hash algorithms should have the following characteristics: + +- **Determinism**: For the same input, the hash algorithm should always produce the same output. Only then can the hash table be reliable. +- **High Efficiency**: The process of computing the hash value should be fast enough. The smaller the computational overhead, the more practical the hash table. +- **Uniform Distribution**: The hash algorithm should ensure that key-value pairs are evenly distributed in the hash table. The more uniform the distribution, the lower the probability of hash collisions. + +In fact, hash algorithms are not only used to implement hash tables but are also widely applied in other fields. + +- **Password Storage**: To protect the security of user passwords, systems usually do not store the plaintext passwords but rather the hash values of the passwords. When a user enters a password, the system calculates the hash value of the input and compares it with the stored hash value. If they match, the password is considered correct. +- **Data Integrity Check**: The data sender can calculate the hash value of the data and send it along; the receiver can recalculate the hash value of the received data and compare it with the received hash value. If they match, the data is considered intact. + +For cryptographic applications, to prevent reverse engineering such as deducing the original password from the hash value, hash algorithms need higher-level security features. + +- **Unidirectionality**: It should be impossible to deduce any information about the input data from the hash value. +- **Collision Resistance**: It should be extremely difficult to find two different inputs that produce the same hash value. +- **Avalanche Effect**: Minor changes in the input should lead to significant and unpredictable changes in the output. + +Note that **"Uniform Distribution" and "Collision Resistance" are two separate 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 + +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. + +- **Additive Hash**: Add up the ASCII codes of each character in the input and use the total sum as the hash value. +- **Multiplicative Hash**: Utilize the non-correlation of multiplication, multiplying each round by a constant, accumulating the ASCII codes of each character into the hash value. +- **XOR Hash**: Accumulate the hash value by XORing each element of the input data. +- **Rotating Hash**: Accumulate the ASCII code of each character into a hash value, performing a rotation operation on the hash value before each accumulation. + +```src +[file]{simple_hash}-[class]{}-[func]{rot_hash} +``` + +It is observed that the last step of each hash algorithm is to take the modulus of the large prime number $1000000007$ to ensure that the hash value is within an appropriate range. It is worth pondering why emphasis is placed on modulo a prime number, or what are the disadvantages of modulo a composite number? This is an interesting question. + +To conclude: **Using a large prime number as the modulus can maximize the uniform distribution of hash values**. Since a prime number does not share common factors with other numbers, it can reduce the periodic patterns caused by the modulo operation, thus avoiding hash collisions. + +For example, suppose we choose the composite number $9$ as the modulus, which can be divided by $3$, then all `key` divisible by $3$ will be mapped to hash values $0$, $3$, $6$. + +$$ +\begin{aligned} +\text{modulus} & = 9 \newline +\text{key} & = \{ 0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, \dots \} \newline +\text{hash} & = \{ 0, 3, 6, 0, 3, 6, 0, 3, 6, 0, 3, 6,\dots \} +\end{aligned} +$$ + +If the input `key` happens to have this kind of arithmetic sequence distribution, then the hash values will cluster, thereby exacerbating hash collisions. Now, suppose we replace `modulus` with the prime number $13$, since there are no common factors between `key` and `modulus`, the uniformity of the output hash values will be significantly improved. + +$$ +\begin{aligned} +\text{modulus} & = 13 \newline +\text{key} & = \{ 0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, \dots \} \newline +\text{hash} & = \{ 0, 3, 6, 9, 12, 2, 5, 8, 11, 1, 4, 7, \dots \} +\end{aligned} +$$ + +It is worth noting that if the `key` is guaranteed to be randomly and uniformly distributed, then choosing a prime number or a composite number as the modulus can both produce uniformly distributed hash values. However, when the distribution of `key` has some periodicity, modulo a composite number is more likely to result in clustering. + +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 + +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. + +In practice, we usually use some standard hash algorithms, such as MD5, SHA-1, SHA-2, and SHA-3. They can map input data of any length to a fixed-length hash value. + +Over the past century, hash algorithms have been in a continuous process of upgrading and optimization. Some researchers strive to improve the performance of hash algorithms, while others, including hackers, are dedicated to finding security issues in hash algorithms. The table below shows hash algorithms commonly used in practical applications. + +- MD5 and SHA-1 have been successfully attacked multiple times and are thus abandoned in various security applications. +- SHA-2 series, especially SHA-256, is one of the most secure hash algorithms to date, with no successful attacks reported, hence commonly used in various security applications and protocols. +- SHA-3 has lower implementation costs and higher computational efficiency compared to SHA-2, but its current usage coverage is not as extensive as the SHA-2 series. + +

Table   Common Hash Algorithms

+ +| | MD5 | SHA-1 | SHA-2 | SHA-3 | +| --------------- | ----------------------------------------------- | ----------------------------------- | ----------------------------------------------------------------- | ---------------------------- | +| Release Year | 1992 | 1995 | 2002 | 2008 | +| Output Length | 128 bit | 160 bit | 256/512 bit | 224/256/384/512 bit | +| Hash Collisions | Frequent | Frequent | Rare | Rare | +| 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 + +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. + +- The hash values of integers and booleans are their own values. +- The calculation of hash values for floating-point numbers and strings is more complex, and interested readers are encouraged to study this on their own. +- The hash value of a tuple is a combination of the hash values of each of its elements, resulting in a single hash value. +- The hash value of an object is generated based on its memory address. By overriding the hash method of an object, hash values can be generated based on content. + +!!! tip + + Be aware that the definition and methods of the built-in hash value calculation functions in different programming languages vary. + +=== "Python" + + ```python title="built_in_hash.py" + num = 3 + hash_num = hash(num) + # Hash value of integer 3 is 3 + + bol = True + hash_bol = hash(bol) + # Hash value of boolean True is 1 + + dec = 3.14159 + hash_dec = hash(dec) + # Hash value of decimal 3.14159 is 326484311674566659 + + str = "Hello 算法" + hash_str = hash(str) + # Hash value of string "Hello 算法" is 4617003410720528961 + + tup = (12836, "小哈") + hash_tup = hash(tup) + # Hash value of tuple (12836, '小哈') is 1029005403108185979 + + obj = ListNode(0) + hash_obj = hash(obj) + # Hash value of ListNode object at 0x1058fd810 is 274267521 + ``` + +=== "C++" + + ```cpp title="built_in_hash.cpp" + int num = 3; + size_t hashNum = hash()(num); + // Hash value of integer 3 is 3 + + bool bol = true; + size_t hashBol = hash()(bol); + // Hash value of boolean 1 is 1 + + double dec = 3.14159; + size_t hashDec = hash()(dec); + // Hash value of decimal 3.14159 is 4614256650576692846 + + string str = "Hello 算法"; + size_t hashStr = hash()(str); + // Hash value of string "Hello 算法" is 15466937326284535026 + + // In C++, built-in std::hash() only provides hash values for basic data types + // Hash values for arrays and objects need to be implemented separately + ``` + +=== "Java" + + ```java title="built_in_hash.java" + int num = 3; + int hashNum = Integer.hashCode(num); + // Hash value of integer 3 is 3 + + boolean bol = true; + int hashBol = Boolean.hashCode(bol); + // Hash value of boolean true is 1231 + + double dec = 3.14159; + int hashDec = Double.hashCode(dec); + // Hash value of decimal 3.14159 is -1340954729 + + String str = "Hello 算法"; + int hashStr = str.hashCode(); + // Hash value of string "Hello 算法" is -727081396 + + Object[] arr = { 12836, "小哈" }; + int hashTup = Arrays.hashCode(arr); + // Hash value of array [12836, 小哈] is 1151158 + + ListNode obj = new ListNode(0); + int hashObj = obj.hashCode(); + // Hash value of ListNode object utils.ListNode@7dc5e7b4 is 2110121908 + ``` + +=== "C#" + + ```csharp title="built_in_hash.cs" + int num = 3; + int hashNum = num.GetHashCode(); + // Hash value of integer 3 is 3; + + bool bol = true; + int hashBol = bol.GetHashCode(); + // Hash value of boolean true is 1; + + double dec = 3.14159; + int hashDec = dec.GetHashCode(); + // Hash value of decimal 3.14159 is -1340954729; + + string str = "Hello 算法"; + int hashStr = str.GetHashCode(); + // Hash value of string "Hello 算法" is -586107568; + + object[] arr = [12836, "小哈"]; + int hashTup = arr.GetHashCode(); + // Hash value of array [12836, 小哈] is 42931033; + + ListNode obj = new(0); + int hashObj = obj.GetHashCode(); + // Hash value of ListNode object 0 is 39053774; + ``` + +=== "Go" + + ```go title="built_in_hash.go" + // Go does not provide built-in hash code functions + ``` + +=== "Swift" + + ```swift title="built_in_hash.swift" + let num = 3 + let hashNum = num.hashValue + // Hash value of integer 3 is 9047044699613009734 + + let bol = true + let hashBol = bol.hashValue + // Hash value of boolean true is -4431640247352757451 + + let dec = 3.14159 + let hashDec = dec.hashValue + // Hash value of decimal 3.14159 is -2465384235396674631 + + let str = "Hello 算法" + let hashStr = str.hashValue + // Hash value of string "Hello 算法" is -7850626797806988787 + + let arr = [AnyHashable(12836), AnyHashable("小哈")] + let hashTup = arr.hashValue + // Hash value of array [AnyHashable(12836), AnyHashable("小哈")] is -2308633508154532996 + + let obj = ListNode(x: 0) + let hashObj = obj.hashValue + // Hash value of ListNode object utils.ListNode is -2434780518035996159 + ``` + +=== "JS" + + ```javascript title="built_in_hash.js" + // JavaScript does not provide built-in hash code functions + ``` + +=== "TS" + + ```typescript title="built_in_hash.ts" + // TypeScript does not provide built-in hash code functions + ``` + +=== "Dart" + + ```dart title="built_in_hash.dart" + int num = 3; + int hashNum = num.hashCode; + // Hash value of integer 3 is 34803 + + bool bol = true; + int hashBol = bol.hashCode; + // Hash value of boolean true is 1231 + + double dec = 3.14159; + int hashDec = dec.hashCode; + // Hash value of decimal 3.14159 is 2570631074981783 + + String str = "Hello 算法"; + int hashStr = str.hashCode; + // Hash value of string "Hello 算法" is 468167534 + + List arr = [12836, "小哈"]; + int hashArr = arr.hashCode; + // Hash value of array [12836, 小哈] is 976512528 + + ListNode obj = new ListNode(0); + int hashObj = obj.hashCode; + // Hash value of ListNode object Instance of 'ListNode' is 1033450432 + ``` + +=== "Rust" + + ```rust title="built_in_hash.rs" + use std::collections::hash_map::DefaultHasher; + use std::hash::{Hash, Hasher}; + + let num = 3; + let mut num_hasher = DefaultHasher::new(); + num.hash(&mut num_hasher); + let hash_num = num_hasher.finish(); + // Hash value of integer 3 is 568126464209439262 + + let bol = true; + let mut bol_hasher = DefaultHasher::new(); + bol.hash(&mut bol_hasher); + let hash_bol = bol_hasher.finish(); + // Hash value of boolean true is 4952851536318644461 + + let dec: f32 = 3.14159; + let mut dec_hasher = DefaultHasher::new(); + dec.to_bits().hash(&mut dec_hasher); + let hash_dec = dec_hasher.finish(); + // Hash value of decimal 3.14159 is 2566941990314602357 + + let str = "Hello 算法"; + let mut str_hasher = DefaultHasher::new(); + str.hash(&mut str_hasher); + let hash_str = str_hasher.finish(); + // Hash value of string "Hello 算法" is 16092673739211250988 + + let arr = (&12836, &"小哈"); + let mut tup_hasher = DefaultHasher::new(); + arr.hash(&mut tup_hasher); + let hash_tup = tup_hasher.finish(); + // Hash value of tuple (12836, "小哈") is 1885128010422702749 + + let node = ListNode::new(42); + let mut hasher = DefaultHasher::new(); + node.borrow().val.hash(&mut hasher); + let hash = hasher.finish(); + // Hash value of ListNode object RefCell { value: ListNode { val: 42, next: None } } is 15387811073369036852 + ``` + +=== "C" + + ```c title="built_in_hash.c" + // C does not provide built-in hash code functions + ``` + +=== "Zig" + + ```zig title="built_in_hash.zig" + + ``` + +??? pythontutor "Code Visualization" + + https://pythontutor.com/render.html#code=class%20ListNode%3A%0A%20%20%20%20%22%22%22%E9%93%BE%E8%A1%A8%E8%8A%82%E7%82%B9%E7%B1%BB%22%22%22%0A%20%20%20%20def%20__init__%28self,%20val%3A%20int%29%3A%0A%20%20%20%20%20%20%20%20self.val%3A%20int%20%3D%20val%20%20%23%20%E8%8A%82%E7%82%B9%E5%80%BC%0A%20%20%20%20%20%20%20%20self.next%3A%20ListNode%20%7C%20None%20%3D%20None%20%20%23%20%E5%90%8E%E7%BB%A7%E8%8A%82%E7%82%B9%E5%BC%95%E7%94%A8%0A%0A%22%22%22Driver%20Code%22%22%22%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20num%20%3D%203%0A%20%20%20%20hash_num%20%3D%20hash%28num%29%0A%20%20%20%20%23%20%E6%95%B4%E6%95%B0%203%20%E7%9A%84%E5%93%88%E5%B8%8C%E5%80%BC%E4%B8%BA%203%0A%0A%20%20%20%20bol%20%3D%20True%0A%20%20%20%20hash_bol%20%3D%20hash%28bol%29%0A%20%20%20%20%23%20%E5%B8%83%E5%B0%94%E9%87%8F%20True%20%E7%9A%84%E5%93%88%E5%B8%8C%E5%80%BC%E4%B8%BA%201%0A%0A%20%20%20%20dec%20%3D%203.14159%0A%20%20%20%20hash_dec%20%3D%20hash%28dec%29%0A%20%20%20%20%23%20%E5%B0%8F%E6%95%B0%203.14159%20%E7%9A%84%E5%93%88%E5%B8%8C%E5%80%BC%E4%B8%BA%20326484311674566659%0A%0A%20%20%20%20str%20%3D%20%22Hello%20%E7%AE%97%E6%B3%95%22%0A%20%20%20%20hash_str%20%3D%20hash%28str%29%0A%20%20%20%20%23%20%E5%AD%97%E7%AC%A6%E4%B8%B2%E2%80%9CHello%20%E7%AE%97%E6%B3%95%E2%80%9D%E7%9A%84%E5%93%88%E5%B8%8C%E5%80%BC%E4%B8%BA%204617003410720528961%0A%0A%20%20%20%20tup%20%3D%20%2812836,%20%22%E5%B0%8F%E5%93%88%22%29%0A%20%20%20%20hash_tup%20%3D%20hash%28tup%29%0A%20%20%20%20%23%20%E5%85%83%E7%BB%84%20%2812836,%20'%E5%B0%8F%E5%93%88'%29%20%E7%9A%84%E5%93%88%E5%B8%8C%E5%80%BC%E4%B8%BA%201029005403108185979%0A%0A%20%20%20%20obj%20%3D%20ListNode%280%29%0A%20%20%20%20hash_obj%20%3D%20hash%28obj%29%0A%20%20%20%20%23%20%E8%8A%82%E7%82%B9%E5%AF%B9%E8%B1%A1%20%3CListNode%20object%20at%200x1058fd810%3E%20%E7%9A%84%E5%93%88%E5%B8%8C%E5%80%BC%E4%B8%BA%20274267521&cumulative=false&curInstr=19&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=311&rawInputLstJSON=%5B%5D&textReferences=false + +In many programming languages, **only immutable objects can serve as the `key` in a hash table**. If we use a list (dynamic array) as a `key`, when the contents of the list change, its hash value also changes, and we would no longer be able to find the original `value` in the hash table. + +Although the member variables of a custom object (such as a linked list node) are mutable, it is hashable. **This is because the hash value of an object is usually generated based on its memory address**, and even if the contents of the object change, the memory address remains the same, so the hash value remains unchanged. + +You might have noticed that the hash values output in different consoles are different. **This is because the Python interpreter adds a random salt to the string hash function each time it starts up**. This approach effectively prevents HashDoS attacks and enhances the security of the hash algorithm. diff --git a/docs-en/chapter_hashing/hash_collision.assets/hash_table_chaining.png b/docs-en/chapter_hashing/hash_collision.assets/hash_table_chaining.png new file mode 100644 index 0000000000000000000000000000000000000000..1c67feeffa04fc0c179fec6f14372d60b51d53c7 GIT binary patch literal 30209 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 K)ZDfT`+oq2q>-5b literal 0 HcmV?d00001 diff --git a/docs-en/chapter_hashing/hash_collision.assets/hash_table_linear_probing.png b/docs-en/chapter_hashing/hash_collision.assets/hash_table_linear_probing.png new file mode 100644 index 0000000000000000000000000000000000000000..5e194347896baf24387c5c15612262215cbfac4d GIT binary patch literal 20486 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 literal 0 HcmV?d00001 diff --git a/docs-en/chapter_hashing/hash_collision.assets/hash_table_open_addressing_deletion.png b/docs-en/chapter_hashing/hash_collision.assets/hash_table_open_addressing_deletion.png new file mode 100644 index 0000000000000000000000000000000000000000..729df3118a3f1337563cd2386f3fd558c32cbcf3 GIT binary patch literal 17523 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 KelF{r5}E)jwqC3N literal 0 HcmV?d00001 diff --git a/docs-en/chapter_hashing/hash_collision.md b/docs-en/chapter_hashing/hash_collision.md new file mode 100644 index 000000000..02495c757 --- /dev/null +++ b/docs-en/chapter_hashing/hash_collision.md @@ -0,0 +1,108 @@ +# Hash Collision + +As mentioned in the previous section, **usually the input space of a hash function is much larger than its output space**, making hash collisions theoretically inevitable. For example, if the input space consists of all integers and the output space is the size of the array capacity, multiple integers will inevitably map to the same bucket index. + +Hash collisions can lead to incorrect query results, severely affecting the usability of hash tables. To solve this problem, we expand the hash table whenever a hash collision occurs, until the collision is resolved. This method is simple and effective but inefficient due to the extensive data transfer and hash value computation involved in resizing the hash table. To improve efficiency, we can adopt the following strategies: + +1. Improve the data structure of the hash table, **allowing it to function normally in the event of a hash collision**. +2. Only perform resizing when necessary, i.e., when hash collisions are severe. + +There are mainly two methods for improving the structure of hash tables: "Separate Chaining" and "Open Addressing". + +## Separate Chaining + +In the original hash table, each bucket can store only one key-value pair. "Separate chaining" transforms individual elements into a linked list, with key-value pairs as list nodes, storing all colliding key-value pairs in the same list. The figure below shows an example of a hash table with separate chaining. + +![Separate Chaining Hash Table](hash_collision.assets/hash_table_chaining.png) + +The operations of a hash table implemented with separate chaining have changed as follows: + +- **Querying Elements**: Input `key`, pass through the hash function to obtain the bucket index, access the head node of the list, then traverse the list and compare `key` to find the target key-value pair. +- **Adding Elements**: First access the list head node via the hash function, then add the node (key-value pair) to the list. +- **Deleting Elements**: Access the list head based on the hash function's result, then traverse the list to find and remove the target node. + +Separate chaining has the following limitations: + +- **Increased Space Usage**: The linked list contains node pointers, which consume more memory space than arrays. +- **Reduced Query Efficiency**: Due to the need for linear traversal of the list to find the corresponding element. + +The code below provides a simple implementation of a separate chaining hash table, with two things to note: + +- Lists (dynamic arrays) are used instead of linked lists for simplicity. In this setup, the hash table (array) contains multiple buckets, each of which is a list. +- This implementation includes a method for resizing the hash table. When the load factor exceeds $\frac{2}{3}$, we resize the hash table to twice its original size. + +```src +[file]{hash_map_chaining}-[class]{hash_map_chaining}-[func]{} +``` + +It's worth noting that when the list is very long, the query efficiency $O(n)$ is poor. **At this point, 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" does not introduce additional data structures but uses "multiple probes" to handle hash collisions. 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 uses a fixed-step linear search for probing, differing from ordinary hash tables. + +- **Inserting Elements**: Calculate the bucket index using the hash function. If the bucket already contains an element, linearly traverse forward from the conflict position (usually with a step size of $1$) until an empty bucket is found, then insert the element. +- **Searching for Elements**: If a hash collision is found, use the same step size to linearly traverse forward until the corresponding element is found and return `value`; if an empty bucket is encountered, it means the target element is not in the hash table, so return `None`. + +The figure below shows the distribution of key-value pairs in an open addressing (linear probing) hash table. According to this hash function, keys with the same last two digits will be mapped to the same bucket. Through linear probing, they are stored consecutively in that bucket and the buckets below it. + +![Distribution of Key-Value Pairs in Open Addressing (Linear Probing) Hash Table](hash_collision.assets/hash_table_linear_probing.png) + +However, **linear probing tends to create "clustering"**. Specifically, the longer a continuous position in the array is occupied, the more likely these positions are to encounter hash collisions, further promoting the growth of these clusters and eventually leading to deterioration in the efficiency of operations. + +It's important to note that **we cannot directly delete elements in an open addressing hash table**. Deleting an element creates an empty bucket `None` in the array. When searching for elements, if linear probing encounters this empty bucket, it will return, making the elements below this bucket inaccessible. The program may incorrectly assume these elements do not exist, as shown in the figure below. + +![Query Issues Caused by Deletion in Open Addressing](hash_collision.assets/hash_table_open_addressing_deletion.png) + +To solve this problem, we can use a "lazy deletion" mechanism: instead of directly removing elements from the hash table, **use a constant `TOMBSTONE` to mark the bucket**. In this mechanism, both `None` and `TOMBSTONE` represent empty buckets and can hold key-value pairs. However, when linear probing encounters `TOMBSTONE`, it should continue traversing since there may still be key-value pairs below it. + +However, **lazy deletion may accelerate the degradation of hash table performance**. Every deletion operation produces a delete mark, and as `TOMBSTONE` increases, so does the search time, as linear probing may have to skip multiple `TOMBSTONE` to find the target element. + +Therefore, consider recording the index of the first `TOMBSTONE` encountered during linear probing and swapping the target element found with this `TOMBSTONE`. The advantage of this is that each time a query or addition is performed, the element is moved to a bucket closer to the ideal position (starting point of probing), thereby optimizing the query efficiency. + +The code below implements an open addressing (linear probing) hash table with lazy deletion. To make fuller use of the hash table space, we treat the hash table as a "circular array," continuing to traverse from the beginning when the end of the array is passed. + +```src +[file]{hash_map_open_addressing}-[class]{hash_map_open_addressing}-[func]{} +``` + +### Quadratic Probing + +Quadratic probing is similar to linear probing and is one of the common strategies of open addressing. When a collision occurs, quadratic probing does not simply skip a fixed number of steps but skips "the square of the number of probes," i.e., $1, 4, 9, \dots$ steps. + +Quadratic probing has the following advantages: + +- Quadratic probing attempts to alleviate the clustering effect of linear probing by skipping the distance of the square of the number of probes. +- Quadratic probing skips larger distances to find empty positions, helping to distribute data more evenly. + +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 it might not access empty buckets even if they exist in the hash table. + +### 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. + +- **Inserting Elements**: If hash function $f_1(x)$ encounters a conflict, try $f_2(x)$, and so on, until an empty position is found and the element is inserted. +- **Searching for Elements**: Search in the same order of hash functions until the target element is found and returned; if an empty position is encountered or all hash functions have been tried, it indicates the element is not in the hash table, then return `None`. + +Compared to linear probing, double hashing is less prone to clustering but involves additional computation for multiple hash functions. + +!!! tip + + Please note that open addressing (linear probing, quadratic probing, and double hashing) hash tables all have the issue of "not being able to directly delete elements." + +## Choice of Programming Languages + +Various programming languages have adopted different hash table implementation strategies, here are a few examples: + +- Python uses open addressing. The `dict` dictionary uses pseudo-random numbers for probing. +- Java uses separate chaining. Since JDK 1.8, when the array length in `HashMap` reaches 64 and the length of a linked list reaches 8, the linked list is converted to a red-black tree to improve search performance. +- Go uses separate chaining. Go stipulates that each bucket can store up to 8 key-value pairs, and if the capacity is exceeded, an overflow bucket is connected; when there are too many overflow buckets, a special equal-size expansion operation is performed to ensure performance. diff --git a/docs-en/chapter_hashing/hash_map.assets/hash_collision.png b/docs-en/chapter_hashing/hash_map.assets/hash_collision.png new file mode 100644 index 0000000000000000000000000000000000000000..45f42fc2a4edb2626000e6d00aa6c1431e5bbd1e GIT binary patch literal 30765 zcmcG#XH-oj$$LvCr`pd@1>0{~E}tEt`w z0Dbxv(Mf_l{j>K`^ug(e-CJ6BuAQ8mtgWprt{hHp9KEdYyIonZ=ckLwSUj4Y2?+@q z92{iyYx&W>v10vDRJ-ly_-Om%$J*N3WlgdP{6xa9l#HgOnexJ^si~sATDf<@OG`_O zi;HbjqhImE`XBDRefze3X+AzazP`SGVrGAPXZv+c$o~F*W@gsUpFdO6(!O-%_RjUr z&dz@8|5j93^dP;fxw(1T-!yTcFQP8Ir>95iPDfi?TUlAz-qCSVa&mNZ^t*TOwzjr5 z4-WJ4@`i_pJ3Bi=!@^cpR#IA*b_xq(e!O4v_L^Hd_&vPy>{tEN{C?~2t=`_=D<)kX zQ|-QOKVoBJ$Ct-TC&xzq?5^&tsz3ZaFuwcvXKh_wonduxU{!!Q?%VRt!EQxr!}!MR z#;l3kz?<&Ynx?g!oSeDst;x-egU?}){70X^9p4KwE*#w2IoLk>Gctp#_%Syf+t(S` zxUuTyiW}U>ZCx(>UGS)}8ry=c=v|weUp(q-JRBHEAMQKo>E287IBKg{b#x$XEcdQ1 zW%O>_HdNxPiw=K$?Vj8oSzl?IXsW8J+6#Z!JhD|1S>}>O|&36&K3wsNbiwDJV8$p51(|hBm$>>^r;5BqS(m~kUo@=a|T-(nX z8@%~>>HBD1-Q?c;wyogK=Bnw5#lgWF*-Jx1LwX+v*M9%n`(BsbwUW`6u`su}dS7sK z<*;sgA-HyWucG`>Ue?}6IId;o)3?R;{xQ4U!Mb0ae(xteN+(8UmO>K#s3rFAHU2oj zWp|Iyy-S;3(Pz%9T-y8)*FH6QHRjEli^AXTu%3OfOap^uEaNWqsAU-`X;) z$EBMb>s{bg+c*6NSMfN>(h!!?QF$ww6cT-ViAuio((TB`FqZ3_Tnk3TVgLi~OE|M;?=efyY==;e8M zCHe!=HIpzY6Rg@W_gM`xazQ`6X*M~MXS}yi%8r7JODFrQB)(fet(ZCQgs)AgTGN)J zy_<;IgPY6-();@yWktW2AOg(8Rtb9(J`kR(a_Oo35GaLmHvyo3* zCxXvqLUZBB*94MaWm1om5Bf*+GoiWpJqGyYBi6zyp7 zgn~XgYp|vs3UC?;ry%R$tV2&5E~xSSX| z%$F`zXC^fqbomTsiRyI&s+Hjjxz(P+=JD?@iu)MI?v;#Ix(qD4pPUHm?-^H!CfxnJ zZ8!Mn?pGb>9X%(`ol-S*q^$N{O=8HhjPQ+)9;x1qS;c|N38N1_NKkZ$ILlC4UPXkG zHjwc8mvPgiUVXUyGQ(3lEeqd`oR{;tNc~Ew#L#=Q+WvWYx8W`OCWUfwB5SPmhXOVU zYd6OWGxw{l1W+yp^|$a-geANCfU`DMGUgk3K7z*e5(&gGd#wrdPbyg?BuH_X9AxBw ze2c*Rw!9b;&LbJs3MrVu{6Le`g$nr4pv+zt6cM)izQn%HRf0lY{rRYocxBq!FTUAyFa1RxK!Ndwem;gz^q- zP$VO;&VkNmOP%t?Al@8`|130s6{QrvRv|?9f6eHsy_pR|96dTBg7|UrLFZBm0o?X> z&)yq{sEV%^h4HFzT?&~52ihY6(8n6jN8Rg-tEzuH|HhsHFaEKCFKM;x3#|?#UJS_w zG01&4y^T1wx!h}0vcUNPchm);VGijaYr2 z2RhpB{lVofgV)WinT{DhY$){M*ug_Cw5=20NAO(yQpA%LKN_<0ucH(#vK0%iLj<9v zfMF=a(?U?mt4KOifBbLO9{SrfOk`DQ{IU(mBi8KDfqn=j;hTbUkzG zm1a(_*xP67*Ldz_reDhb#Nwh^OQE@yulsb>><^noe0wTsHwAH@a~LyjQWPB_2*v9% zP%bmvS9>>vh~>U|^RO1^VVbzi-cwRBBtITB&~c){ z{!wOjjCz%Q^GbRExzqldk^7PVB!O1)jEd)XR4o?vQoTVgSics;RrDv%h%ks@Nmbuz@Fdg{2oe3_o2N@a91%mV)rW`?}Q`Xr{#F5?}>F zdhaXUgwrj}!FBjt(Dy-Td!9GhqpZi`py*i;kh>J!f6XD|eYTwwE&jP-5NnGW6w}!t zW_*ELk=Y_F=KKCtIEK5!O<&SgSHYX{v4E0Gs*obt+E*3C$ZZZL`kE|6IWZIn#^Pq4 zU%}BdS<6}Et5ck#^ovxNuE}D@YnwpELK8@O3!R+D%Z;IE8ypECO z(f*y#Rh)DjS?iFgL(lzmgwFxg-oA|S2Z-xhrWh{?=_5Od@rUBZrBXnndTDE$NB54x zLHCVfanLP0*t4XS24?h}LZAbKV_0G&g9!_-MTRK zxrTQavI`!HGHN%a2w-|XI*ko&hT&AS=$3Z=v=Qegp&nnl1DUlXuU6ze-;wZ7&s!us z#d{w<63)wxv|#>uiML$`QAM&SVKwMWnV%@Y$sOrEE|{;rT)&*S)F+Oi)EC9EO3xDU z(hFs|T!$2caod$)*Yphvke3zA%kF^s=I^jSf(R1bQ=uOd1OG-DIbOF!Z(~4urF;0ODC|!d7 z<=2cJt71=XYQa3kj7a?GFhGMl*nAE2)cOur!f&|_B4Nzs?2JhBn>O!JXu($oD@|ZwH7Xk%-NH@`DHx84+*LI2M2T-K`o+wnvG}^k}uW?hYX4 zo&&MinasHEKWpP@`|kN4asSYi$|ec0EHub(WzY&d0S?BBWX?!+0^i@2;wzw}S?vA! z43Rh`OXWSs-zHOyn5uL-c&<)?qG!G#qxXp>I*#{VU4=j+VafX83q^9x>!kEG$;|#Bwn&cwoh!>9l=` z*-qQniEMlg)Rli$?go_=?L+4VSQ*HJ9JHVxr3SEjUbt8c&TpIGDqr%qY|U8 z`JY*bqde4`z9u1KmtPN;=gOK5KP6-TV~|X~rulcp8b+0o_hTk!YzLKe;8ljr zZtEUXMx+bRK0h_&+c=Y2VBp>3dkr=(WbQNXLR1AzdsU|4jW*{ZYNkixoQI?gqHqZV zlN&KyzJTub@m#Vc@L*h1F#?Tr=ZQIEaqMVs9}F~_CPFqIk0H%$+SU8KE5XO4&^ zL|gFQPahq5s#QDp^ik6(_15f94-Ky$s$~5>=uU_V@_twONhOk>fG1Kvxv6?0N>y+s z;QO11lbORFCp%BQUl}=hK4MqkC}gg~Q6X|uGt@C(=?W}-`9{)GJ)!&DnI#=+e6v~F zfrtI7h21;Koh)LPhd&6~F-(INzAwPpHO)}?uqd8y2JB^A!yOy7(LDu6-RJOxTQhG%siE-khh?Nfem^dUpmI>Omxun?&{r~R{ z)^T4+mU(oZ47tWCpFc`r`qsZ4MS;~aWoc&WQ&USy(-3KIFn$<3P@jB)>y)H7dsjH9 zRHtPYCczZ;;f2zY?3YN{FTZz^6ArT}A7j3_z8y0dD0`@6*I|{YWMK8n8d?%q7A(>k zMjz?NUS6g%w21o8uz9f4#MdEgDa14|)zNEMXao+`Jx?-$=izb98hTHGOS6>RLdkB` zoB>O_kMK$k=Nm@nrxeeUM?5Cnd&8IT_k#f=*5{rWGd5}b&EYH}y6y?-kYjn`_fW;G zc}m*^DYUxkq3OHyY8!G1jka%gY;c$M>#0MUTpYh|USnh%VnAoe^ERB6IQMZSPgKxk z^w~32`dcxovukNo_aWmz;%%FT?1u@nWD*TD(Jb`00?!Hs0muI`{!HGvm9i0Hd%1?Y zIY1$f#?-Gn<0Bl)$P$h*=2>z3`C}rliKb}m3|T%#VM)0`3r7E!)Nr)y@ZIBQ8oy;$ z_q4Az3liI1mkKmU4;EA-y$^2N7;=^*kgq}8R_Wmte5k}8#ndnJKfqTyAxk0T_#|MXIfBNNW2+sp{gayzMew}O)zr%e}}|D&@p zr++!@@&Sb`S_PHhURe$niPa>KC4LCar)=R z;d{4xEgye9>UWm3Z$o>8umouY+SU`-Id06_iwugu$LZCDpi=cGsVy?6t=Zuvy{v(` zS*&Gt4FlGzord~{({2nREMNNNN%+nGnZE>AhZ^~U275(f&1?two9a(HH!05O9Ih=( zEjcMQn#+p|D&gM~$*9L~!{)T1*{FZgaQ~M(G{S#Hsj}9|X!3y25JPkaP2!z)M1KCK zxzfrpru-H&(U}o$Mc%lO!Xaf32S_>aaz07IksO_74Y`H%e6LZ9(5`U)OEJuzT69PA z8A9gTZ_zHnE{1q^39sBj7HaMmOZ$ZllxF3r%E(!+vZDQ5~EQ~|T7E_hoow=3 zwM#U9hRh!*W5NDZM~LAQGw@lxL&vyJ&cP4ej9@TH%aizq>3Nr~CsCogMahN^_Q+lh zZIq3wT^zozyv?)uQqB9bFW>fOt1TJj+FHZHzxKnsM7NSrChJVMnDBJzM%ptP<6rV> zy`YQ$g#$#}_XB_Cot%zBsiu6>ZL8pJ%dI^}5BmFvA(hM&%{rpfX;T(45{G-!4f?zY zx|O9Sy(nIOAt^@uR)FI+XB}!74d5re71kc9gGUM#KYrsh>BdvG-^wJi3RmxYa zVT1UxP1J%k#kC1#0mRcf;W?@b@>E9GBc_NK=jPN%iYcgzgRn*lq76LZMMNqFy2lMA z3C54@Qs>_t*F8;dkgW2Q<9f?TTmjvBPY{K6{&Z{xiq1=!T)o`?)g1qak7Vsnkh8h_ zv{K^Hdm7C-B8+~8^{`an)RWrwrkKxm=YHi1-lX~UUPb-f6Ew-%X4bRINPb_w2D-og z@&=_7gO`+b7-+vGe=@#}clW*KOd2uhl8ZodXR*((OHUA~ zld91EGQt)-7^wi4B`wn~3pA?061b_a{)WmjAg7xZx~;6rkzrYHz4gX=;ZQh6!Al=b z?3)Mzmhdlg(gJ@ca3|v%I$N+ydt=dF*v^l&@kfHaTd2QjclKqJAwptb_-srkC7k1G z2H#VKq|Y^pJ9g(?Y9o=Pd@(bBUZNBENPY|_7aK$Dzm~8=!_Dv?gS&9xXc`cu{dK+P z0j^O@2j7@*HhkU)w;!@}0pY4eobmQCzucc7kouoMWKeOgvytDkDGd&zc?UPLVU>zED~{~rb^v}vJGi0zLaoB z8dvh-GXKo0os%u94F5T^$3{W*zY%T)0hwF!zv4*?G$xiWFh<(il$q z(!!)p5$r|81F=yF<}Yjn|ESv>&t8K6GWde{s$s7t%yXgnk-Al`F*En#877jx-~BCeNEg@w~XMo55IZ=HwY4_ftIb zfALAoShiq)t~L@TTcQKTBr~%6pABk=tn4^ENoa`T{#}zV7Vnm==)%?Mxxl&3?)XF; z_pN3BXoo8K+rpFQ2hK|u|6P(}G#2dYi=;(UWx3$}I!}Mll`q>?R$n~Ca65d6syoR& zo*vroXE(%Jv^W1-R<((OT5?yg2C^l`~cqT%p{`Br9Ait_-w2RnPsv zc)Pya6-K;LNB>v-_e!y&cK=qKR7*6ca4e2+M12s83oo!^EUO{U7YO&-`O1^uN;KGb(DtUpwsR zt^FrRH%Q)L*a%MAi5qm%gx)3+uYWoWx7>aXxxYjxEZYVW_z+&glMCbZ?{Td``2Ubx z@}$ZNafA98LMqu#mMXv{XUc1PURr~FdHemR`7j@6zP`iYlJ)Pd*%~LiC3^R13CBeQ zLv)0gwx`Oo)Bf~r6MV*a3OZ~bWBpvrc=|Q9>9MT2o|=X~8QJ~lM$FH&^S9OIR0643 zFK^M^8_|%J!85u>Xtkq%7Wu<8?1_;HbLcIi0|R;XhH<5aCkNHzCyI;a@>SxiDs2Y6 z-$hc%VU2?fL~D(?=_s+U=uF3gxXzQrZ(@X=@CIk8+YYzj9cxlkaHqS4WX*bN?~v6Z zpm`S&go+zgI$~-Qnm!IVBp1Z_Vm`i8P)|QBlF*z(U?ZtWU7~0A_h0329L=nMN*4)j z4f4!A+86NMsIygtZo{0D$$YNRE%k2~0&c+!79&OeVnE1_jE0M>bL5|h;t>r&2q~F= zoMnRbRM6H&R{^rq1uf5koS_+>Nt^+#S^VmPVl zgnORj=W!B=e2&nX`d78Agx^2ncf|ctULo!gwf_s8(WAa_|77j`0*{)!kw|8L%?&aM z3L8?B)BS1To@L&lPwMcq$+*M6(fyB`x4$3aUX6}@u!ab9KRf?wnh>!hhjm`K4RvcT z;I&lU#{`-1FHdNV&#V>s3j)P?W>$$$uXr9G-4elt$iDUZ%3#6rFZS(}mrB8ECwB@! zkDaqD*CFTsvMeg0Wy0M9gW{EtUQ}c*tg@N|2z=CaS+tCsxnGZ~!cMI&Z23Qf5*D7C zCEzRbvCnGzf5I_75!`bvT^3UoM#_`rm?Qc5U2ZBu?ob4Z;lA z{bQq~f6Po2(R%-NZJ$94iXTtu{fD4*IUZhE(r#5@U4gd>|)h$6R4+tEUNw zuowSww@)+4h@Yu=AuWiDI|breA_?*=6lV1j1H<(f@XkBSEHcV0!QbzQ*!V3yqM^3Zw7H>}q-zaQ$r=M~?0Oak28HLpYpX63UHfDW@+PJaLm?owXG z3YJk@!=7|?7Vd|D=Bh2us;+N zEm#ITC^RVuM~3V5-J;@~rgx+0 zFbLbr&n}(hz$_|i)Hv?cg|uFiPmlWS9aKFLYT(f<(J}I1YxlGNISXoxImGZIvoE** z&g;L_9j40!2N^uQCD{sOSWT8@XeHF~LUh@Plp87@rGfDTMrf5pZ|y96^-gH7Qk(Rt zJK85I#CXc;V-zaxduv7qDl0!q!Tv;iF~ zXbcb%$#>U&1SK}bUwyz4EpBtVMM8v_2_y1oTz#3tm*cl~%ivnqoW{BM>^y2@*-O65 z6#G`7w9e}B)^%Wi7N$6_1yPV<5E9qOF`%)V%%|;|QRsp6`I;OXqWmFn4wzu-*+I_t z&wl3RN1-R=w&m93oxGgPEM@TvoTz*vt*I3F89T;$+cKm+H~ckEXc!ny6+ZR%@UOp4 zGN#F1XETiv1vBqmfo+-CMT10UoDh^oDTrTlRP@COJ?YgSlaFz<+~Ij^PJpJTqc?u{INq9i3`CxieBR{*C!+c z`PIH%N)|i|zYBpEscZc{D76BW*J;E*h_X4IU*3TqQsVC1+1!|uL%A5vKih$-f@H}= zJfdUc)u zE6VZ9Rr~!25)*~zx#kRYpHUFUqLWFH4Z3OpbB&8WP@bj#D8Xis%E zY8p-{;;x$A23=KdbnpYRxe!r5ofiW)ChqG>{ExFe2ZQi%)}r0!_w_&DCixUkPyR5i zG~@8zbsDQu%r#l~825p}^b^1j1+?tTVX5%B`3zXbPMW$av}NVIi(eRVVZ)Zt4Z}dQI0W1R2AJmLMmaGPSsXj+VKq zapA|zMIgu$6P@vaUZM(8UD)BA`7rD@JGcL|@`lp$?ymKL#1~xwSQc^oJ-B=iR&D3~ zhURbh(0h?h=Qz@A+|VG4$l@}wnT(teI-i`Xc~ha%el(@O^N6EWQYAun^pV`@7Gf56&PQBm>2(=+9Yr#toH z(o&-K-XVoh8{gDB2iOX7iU_f|KXPYuL4{i6Qc{xe`m@QeE6d9Z@zPe!w_nxSHrQlZ zr39eBdMFt@m(n6;O6L0R27@jaIqs^XE6GKS*dWCk$|czY%p#+?eIlq)IQkp;^c0w+ zw=XT#jpF5?6FK<2*?Co*gX7kl@Qw!;timtLCvRYK z4-b(^Rui@t`

CA@#|3j?R@Q7m&q~SziG0RHfy;Tk$B|@psfMqE2LI7`UIEthYBK zO@!6HQJ0@C(v}FH&|ng$X*cP9)qB-kzlZ7TD-9Ik?>Ur{F|U$pu73V_b7lGaT1KW9 zi_67In^(7cDAmSxei1q5?5US6SNUp|*FAbUlGDF<>^Zb`+bN;#ZSJ6>M`8ILZzv-we;RQ}PL%K}Jh&yO)pZ&#kk7gG5@&8mXUJ1&V zJ(o7S$rmB;lG)xinBfn3zaz=r!+OR)jUTjBtEqLkCbhmw(6Ili<7#*;G|RP2Z%i_< zuuarG6(%)Kq(^q2c*?4<+;aEjtxpM^B-|?qD;s#qO`w*Nf1(JtsNwGbvmhnJ$O8Eu z+RdPB*)V=r?ub8*ztO6)F=-ZGT`PQ4s=8$Qo-t@cBYP(tp(=8@L5`>0tsvdP@OF%~HuwR~c^wOQHC*|g{K8@Fc8V5P`+mbLD_q;st=BIr z)cfBH&~?B=d2H=f^I%P#`LJmxuXyZzOeF=5x8Q^+>N^W8q`Riw0;meSP>OZcQ#W@kDyA836uu(lm(?zQjmg`V1gvoUTPT|jz3Tb` z5}BFb{Pk2Z+8L)*$$x%yoNh;x`H%&sz=*z4BC@bQCCQ@1`J5hLYc|-wZM=0Cl@q`x z{&(%JUjGTSM9IeHr2q?QNh4F$8wGE{V^?V>ceNdKz@>jMZU4s9K`igGyld{v^X&17 zy$Iri?|K^-jeQ?CioAQG@ekV;Go*T$UU}dWi{EjGb_eZApJ6ge5j_5Ud=IZ)0IQ4_#ol+Xlc91UcFa4hoETojpiiLy2 z)Tc_~`*HNw-{$UqV@%fi>`Q?m!ZIEF8av+1r1XExeq+Q9@#%JcUA2QalYHpXO%Z@ zbR0vcPaLFL)SIc!Ju=jv=Y5)7V9KY~8NaxtPL1Mx2aRdf5DHs5@S&f&S{LuKS1~)*#?4MD13ALcw zbnV*p$S+>z8$W?d|L8+2d^E-)msA0QL4^4O@RVTvz)!68%&3{y0tB9!OB1=z77MyW zgHzw47hv7o{WIOMH8L|b<1O1rSmZ^VE#fPw@PubIvj_EQd_~!SDo4wAu)BZ7v<5_| z|B)~yRU#SA)VzYyhPc54MoOG&xbLg<<~8OaPEUZ5o_{Z4cX5q(4o!L*V&XZ71^x4? zDhDB0(;VzcjsNkczO|o*T|JOM0R%={7lduK#ri8A&0iL$7;*qci?JDGv2{GBwPkb- zl91(mH@4b!>9X&v8`H8RTqDI5l)u>6pK;@RjS!E7lhjxrnf&irYB2Nz|K3SjonRWs z?oKd6!mrW38K^vhX00ueqm<8of%*XdjzO}({7~$#wQsY4ko3h%|2faCM=QOeLrLuk z8YRP__i%+B$Rk}T1n0sgF<8F8rXiDnG$C|nk6ML$iL+N zMTr>K*S-Hf`7AJ*TpiHXYs>*p5>?52*z=Sa_CJ4iG*#?SQdvBA4*ZeO73fCFuB3+5ro(OixEay(0g);-+VTng2dW^)|gVNy1$ArF_JzR%s(F8z%Tqz zit=8phdS?o$*A)LTuOn%X;2r!)`gQqL%6n}s&CdS)zriodJuf=am#3@^k3`1Q|tK! z$}Lc37c$=uL1lUyYC{j{=k7>gOKtbXv^{ldoM&I04+n6A*pDZlWZd|v zAJ?YsQ3{w@KmWX@?wQGxmnM*&Si8PlO$8f@gszC(DX{y?A9~6!5~_p&3&p+;cjJ6c z#DS-G%~|c{%&#$8%g2O_ub)RZf{s3A`1OVz4GGv3orV8keqRbeGrDtnoWzJHsaz@A za*FU_gwm(OyR1|c7eMfbLPImvD}M#xsBE5TGK0~VD6IS8x1I}e!U13$XEZ+2&5(9HYqgy#spz&K#vczd$e}InhkIW(&y%+SAFQGC3`wI5IUr z20vqiyXAZ`gMQ9K!D8Rei`k?$WNy!brt^(oT~p89CF?}3eR)4rD-Ap*NOa^Lv-eg_ zOjlV_;5$jM2nmIIH+|cbEIkA%(sPJ09(J-KQQzdb(JW3Vi(s{0fB-@t(Ek>g zsR|Ce3%T;agNZrF^cy7f@OTM?QjGr5O))i4Okf9t4SVm!%6{BtG6rL2MRyKu6kvhp zKKV9l^1cROddT9E>mDo$s~~8;BC{9fy)c1|c!}@bT`uCs>{nBAo}wmYNWQA z$A_pa#y=bbD$a@Vt5h88M^{UMB85)oi!%sWxa{{bM38^I@JiMjOAB9B7C~7U%WDwR zeR}|Yz6w9*3rKVjAL&`z450LS-F`XlbVLN9?TpOWA|ROvIv+Dzi2X;U(W%N6p^yyT zVvxSR`~E}nt|bCYC*nO9h?(~Va%HX_RVOmRJnVeP2X|I)KGB#{%{dD{M@VD=Lq1Uf zBn!e?9}r4NZ~I4ld@HefK#!X(W=unJM|fRFDT;!BbTwahbZT!qUoa2|2_Jvry<35W z@NEWn&-e}#;~x@)qS>?DJ7H6cOK`AGAaR9Ub1(w?q&tO`s3u3!>+}>_!S;5s!^q_` z?}#TGR%tz;IyDZQT7fJ&H(c+vu03P5>t<`Q%oa0TX%+#$0Em>4G{e`V{7}SWQF$Q! zE-vBG{Z<2c{?XzL2)}%(OJ+u=Az zkx)h}PY2&1x@8A3g83;FO%DIEJ9l@(s6mN zF`3cR2q~a&J@zD5novrN+l;kk_8^WXiQOY_M8p{%#Lx5ZPd4u~1p|w0{;_m``}vDC z5bun@(a_um(Z;xJGMv%*U-RHRX*M(Ls;+|j+@9FkjCZSd0r0?{=&gsFU;W$SLql=(!2q@EXNh~alMcLBHy<~Y^MiXZjXu(Ys_Ys#$IVTv>cdfYUrcS*72H92 z)r!KH9lK9MLS28@;B;Xzcij*`MBdu)QMOtVf^MhOorzmkl3?M5nD>Y zgrJS-E7QM)Bm{5bMt$Z5B5vQ)x&+~+@Q*)1VF+^)oc+dGXQ^0X6p7U^Ld~;oyvCWD zn_J|rz{JKz)!Nr>n|Pu%X3yQ73o0x>p`*nusS$+XWzZfed=} zSemvUT0E4O#Q3L`>Er7t#iYOgID$-^?p38oGQ5W$BL58uPf6vQzc(Q~vxN8Bae3#}-swTt$Z6tfO3&>dai{`7)p)iK>b zzORNLd|}mWRdy7eui$>3;>e=3`T*I)22TEj5?X}Ye$?cCdxVz(D=#iA&NQ&u45;8A z5obpFEy_Ju5g%!|;ljNTBH68z1on8IT>h!;byB!u@E+;0G@Yt4OM+8=n_`N>_Z6I` zE@vb)Ac7s9F8D;9p0DNra?KYgur_K0Ss!wIuTlR(`N_ivq1-JqS{NBGiw<|M`0VN; z@xGfT6Pzmp>nmTObeCZZ4wRnEJ{Ls6k^$utK;zpAz9I%(LWvo$1MHHpJ&o5@#J~-@ z%g3@R=U5i{&I2veAjwgg4`llB9X^amPCe4&rU!v3(qIQ|kyDvRn=KUlAcNqvC@9Qy zf&aaa{CSwI?OV2roCZ{-*MX!t&9)%CYRjPt25jj1=ehU%JT?L;utc!|7{a4z9)ek1 zYVcMULU}uvxR?@HBJtzqTez2Mldc*9(2uCt3mV*X2|r#=dK88cLAQFQsg62{GT3pZ z{R@h~39yU83o&H^-pFkEtMy*Oj9!|LU>PZ($9-R{Y>*tod@j)AGGdfji>l$BM=G?o zDqcZsm`B8$nca#SaXUM_7{Ph3AGxG_m6Xn9xHl5(4F0sweczH>vjJnDcd6ota9zmk zzN?&c@T=>aN#R`bWQE0#)?Y(+Oigi?1!iDqtqK+Bb@H6u=i6h|%eL}30{C4nCVr7Z z_gdknB603H;%mMaO2qr2tWcc} zI;iac>Eg54lGWSOApQCKq%rGh$z1thcqj$lGGQ)}tAV@BEjok4tgNrBbB4_>f$QKl zxxE|DRD2X<%bWZGDbb13OXZG55Wy|3SR>Rt7Y^87)Ib;%KZj!-D(UZvOsPJaI}(Md zlj(fU^>niYL?dLWtbqd+et-syTyX`0%qW=gXVK+0tUd9Y(l3-G7DB)k5+8R|JNPu&oG_;1z!G?Suih{I#j( z>*-NpbK}iS$d?lDVGGWHryoqNzz#l?cpkLH^!lW`y*o$Z&UVkNc&zc)8J)dX3XhHz zI2dn;xID_z`_WmUVnH4K+1kM`V$?BDC~PQ+^J z{QAC3|6;0TLFXl=?;@!e8oMN00iNs?h|(K9E~2d<1HE4MBrH@$14IZTPxg%rm;OT8fV;EFy9^oEb z$h0J#CJUfWAB-*XQuL+Uk3XU2zK+&0vA-n&;C}wMuYNP)B!BgeB8o+3A@3y6*m(4v&$x;dK1YxXFt1cvs*sM7EIaR} z`fqIAr|nv_Z{tlFQ7YUUNH{LO%yB^$cB>`Nn*nd#ICENfHGUMq8;5Ot#-Yz;NBxhWHwi=MqSE&oI@i@+!J*| zHx_zd5toOAHv@KRJ-7tz0=+R5=0Ju2f?P6Q;YU}ecj=YvBv-E!Sv)W8@Lj_*P8TH# zI~H&j;9e=f@^~7bL>0sU)9KpAfayI!=eYPaFy!ywk=?K(4kim=JG{>487_o&VRwA_ zNgU2W=h`yl#up3SsB_@owg-ZzPa%a+_}RN1*CI&PjF>UKjssXVaPxW>8z3f*IQpZ_ z9eMMTVe3-s*0uYoujJTh7|6=GIxYQ(oZeF44#tUY+W-NmEv<>ya`-S_FW`rpaI3fnmb7TEGRo zNX4Q^RmItS*cx^tQrT-W1&m@4!)>ha5=!iwbGaj$lL{Cxb9 zZOPSLW6rI4${Tg~YLu>hKfa%muGcUgxG&BtPaod?>D%{FC92O8$4Hl@MQy)g-jX773@F)a-*bCYOG!PNEocsF_41KnO=VSEG@ zj%ybJ>-D!YrZa$afZ#XiNGPpwtX>Mv(mlO_0(S^o5yWS z`kpt)5fW26&;eN}0|^e?2Z?D}xaIptmxstT62OlFJx~>0=INfF2nxOl;%I;talU}o z>E4(j2_Oa%XF(hlUO5f{gM1p$4*v0hk!J|}mw~}Q04C9LY9fHZDFayqObX$OZGY+0 z07DI6GIm0Suy{xX=!MS1mILo%&ZU`Hp7#Y$%|n5U+y1?%)1^i$JL2?yA3a2okrX`B zcoVmc?j(j=HmhqHiEvy%;;Hz!Pfi&H{!RC?+GX19Y_Z8{YKs+zf-taiCHdf9R1JWQ z4n45HlUsn(=ks;~Y0w+hsw1e?TQr6ilj(a|aX8%*NH}!7UkRuOW8*3qMH?(Wn_sZ0(rjZ zm<{JQUhp8t}UthN9HMkCYtedW>+duv~zv)$y%KyP{|m6 zFY*BjbBBZ{&G<}xLB!co^^`8u*B?jqWBb+8Za<)-%Ji#FI&zjQhL)nj*77A!sh9H_ z+bAAHH$1S*T6Z6aVY$fX_wswT{F=J|0=M!{lD+&P;vj7POV51jm?5!%fEp_XM1B#4oZ=bGm$$49l=YvPe5MEJt}R}r&Ce$x!@AB>vn zCeM}9_RQ0uCwfw-s{5Ot!oJDZpc?mn_#PZ#aVE-QqVp&U!JD@K&djQa8*P|y#p9y? ze82C>{9pN&A@30ulYbHEsr&D!7zV8bacoPvP#^ROAo)rG|3AuK%<(*`ey&cIPjnl0 zBceD)<8CZxJyf$%!Rt(8l2xKO$W;VW*^gV}&*lj!=x*vUj4{lqs+k?iVBX?aUwEUL?Tb_D*M z{ZPGol;qH)!QFfBV-O=Mj`Y}PevG5wpEMx;sUGl#Oro9g_9S=l>yHC#3Cvn;+25U& zeFvLoWWR+pmRp~Uu_iMkv^FR>8_FF0cIk#uBz_O?lF45>l`)?hzQt?RSkurcR~y-u;`uQ*0C>F3QTyW6mb zK0XREw->o*+4SUx4p!qPsOg9g0-pnwPsv5kVrs{zr&RtiIgt zv&ie#C7*iP@>r%nORh-zwx!tz%kGBJci69vqM6r2$As=ktuWLY?XuzC1gyJDMASukBo&#LZMLR%$bLt z-TU+YeBYn%_j;b|dVa(C<6PHS>t6S?@4fcg>)h*gvku>G*ZWob!Jk$4;`cMhD{ZyC z0uR@MRG)B2aVAE~b023UKXZ^15DQdn>>^V0>#s@RaqnMj-eUN}o^?+zH0?9J2~Ilp z$cB~Awtn4^c&3|-sJ8S5Bk$7Fws8&0*q12A>0C*? zsl1zy8GJ-J>#CZq{bHINoQtLoMHx=FnzlIC=yJ9Hy3 zrjq4-H!}BF&k3kCzQ2l&0+y9M-$ebK~8_YTeK{?b>vSIe0 zYM5?UH2KGZ`qH6+;alzGRXk8QQ-rH0^rc6pdZre+U&A`9hOfdbK+k$2>>X33chrj@ zvHV2SIJRbuw48ODTZT}qS|67PUZT}!x0P{1%yPEf)yFiWb6r(}ee#YOW+dj_z>?N& z&*C(0G5d_ztxp2@os7z-aO*naTgE-TzRGphdmvEu-n;hOP4a!U9^z2lj7r`!+oXUC zD9Y~xdRLrv8fnS92A64MUKRRv@4EQc z5@R8vo?CKlfVD^by!VnI-k*d1yQ&L?$%A_vwpK7>RC5BFaFzA%NsZA)C^3tf}ZD}D*%op)xgrb zHbv9`ZgmaQIxl`h+q>$@E23D~$qYWCaR{_^LJ;rdd9$}JI~j=-eY3so zwrC~b{FBT;bJmXIZ46kspvYFth|XP(wf=!5u%r;wD~h;B4;!8zLD-|lXDH#FLb0_X zVhvna)*SMB<@G4a1ntjhIW^3hZITPS7vuYCF-jj$(fMFI9<-=*j{IbB`GH(5x?lHl zY+d~N4I%yu2VXA0T4tOvuPIBJ6|)lOX*zpVO7mzb&cXY-Fwl7Ld2cwO3khxZIf28X z9%fhzJ_`HlUSuRh(_C3(jNE}%gApIkY42g_$ zPA~20A#x9BhVmLMK~gDMJ1rg6BYu_7k<7#+E~c2%BHb)ld?D6-=N%$e4@UNfJsc$~ zR{l%@s6D;<4-pVAORiA>^xjW9E)!L%L*B=D-Y02IH#vj$aR$8t!#3qF1L){1N;UB9 z&hGe?4GgYDs6)SbdHc^}5mp~?6sqRDC5-d#$UO(Y4jZH=2xj)`oRVzuE+DT1r#I7R z>U%7H2qq*IbvRxW#nVIfJH6ju2T#VjB&%4~t1+pf%da+t+6Osn1ijqv5bArm%qIr% z$M8EEv>aw5L4rxrRj%#PckHKxGMd;wynb!7(5&ne>d|ih z1SM<3w$Xli0d93Qh5mmdDu`QysLCq}R`x<_svRFwKuO@g+vZfO!ffc1W_wE}M1Gi#1Tk_0RD=D_mQj_UUA<=3?FCL~?j&YJMTC`Zn%7=o2T&=V zGlEZnVYNOeXGxH#4ovse>VbDe5$Qxnf4|xj@dm%dT9kH!`{D>`{kA7^>(Jvl=I8T@ zkmu_+Yk1{mZ(-~W{)027U!O2dz$_ClB#4@;83LJc-uBJLj5nB%{bDy&Ez1C=uH#Q2 zc%_KaHxQM3wSFiA9Xsppmos(59TG!kUR&X@n@CcWzJ^Lr#z<}P_)X(dz zdeD9H)d#+m6J2SszIV>U0xX@!s7Hl2v{smZb9MTSVuIM-6KW{I>@zayJM>W{H*ipd{-m)X=*;Bw7bXMI96X-cymiudotv*khHVGai1_jJlLQ< zW?r$S98rAL6xRkj=Xgae`N^J?$Gir06G z?N7v#dbP9{PLv4~S8_C(=U)%_&EEe^>+sTMqMo*m6l)-OZ zcn7w^@8p9sJBNdhY1CC+J#H%HiSTgluFF>)*Jr@)fQS!k_ag1<$Co;thdI@Pq-9p4 zE0<;9Z{e$JUC2Y;8l^o;^%=z|G*Kit-V8b3FhLMD_&=zeO?sF8Y>jWhB7f=A zPJc#8;Ny;v0b0$QcbLO2V|aKusPmIpls58iYhS=dEyQiPc}Ar+y`AS$qIanBTF7kr z#j|>{{$-|T<0~VtkA`&{Q7_Z8jqc4a6*i}T{@J^0llG`OjuTQVTh zdxsZlYe=Lx5h3;C+UuiQQLtvs2)GY&pBW|iFMshIj=<1@x-6F;p<*H?Z?@HutX-98J>ljWa@6;eZ7{sC%hJky0hys zsW3(ptkKU0N>F%~G~`rNQuy3~H8loap8lGg$W1yI@pk8zO|y8jju%GNue=-N)UT-5 z6$CzNdK4!&O5>$;NP>A^nVHKY-xtExq!_P863>Ggy1sq!`)fq#<_1OiC};~y2vlj_ zQJ6u2L;9PvhrYvz==9wsWl54F-?zJa-<>FsZU0owPINt}5bbf>HL5TgxVK6+Xp#n=$ zf9Qyi^(BH!mn_TsWmh|;e}g?N%t;ecb2Rbx_;)1V$5Jj}>aMuP+F){N@IJ#x9nToa zDz?8hw(*gOzn3cUnyQD{n4d$#sn90bZ&ByCT^bXBvKr;&=EiKaBxnfc-r%;)b)XI+ z?~!ft&c1r*2g1DoK^2&bJ(}}@au>-Axv)0Nsv&?zTkUYtb+q$G_4Y_+pIXiEF|Fpk z@vg2YPtde`6_%u~_M+<7-}(HllCt5N1wB|#HHN&4M|V11FtFsdlH zIIxW+h*2h8k~)PqyL6KW+2S&ENQ=*DaP}{j$vtxd&AVO$AC&nAkO8FxP?3J?>+krl z?0(^so#~k*75Y*|^ceYLAbIF?8mdCM3N#sipoS*YLC*~P{ioo~Q~Gmh&KikUvN6gf zL8(W|&R-r zlIpiR48WHg(ZhFsfhJ;nXneS)!qjH|+c8)STycd5BA~%oO5%f~!iP7lWIR*CWN=It zaDx?kj1*mJ%2R_QmvoU1{1EvS4q z=qdu;3hb>OU5nQ(K5d~UK9p@@tq(jm9lryJ)1G3lHV&-PqV>v~pO$U*s%P}Ze;GO# zVK#gz1!biLINC|j71SnIfmJHVcYCGZV(9iOJW`zdeat9ftDd5Pfym}aZcB(Y)!k$$v8;$Z2q zwDX4R-q$+NF9giM<*ggS=1wjrwxYX<_XD|q6{lpZZG&T&kslny%UWH6>&$n>w(5NN z^@V$f?4}O2UowGY_7DoGBDONOZVK>(PUVe-Q7_u* zx7^&JnZa?JMGlINzU$%cGvx(OHXi^biF794?@PaXyksBL}Wo%-bYotEplWs-`es}M5RVoyrSqi z50%+X_+|(l2mTy*2^R%(SWt!7@%ang8BIN}+pCnJcT2oJR)evtK$nGq#nqi~NlE>6 zNNQ7-u@mJ)MfBzSrMtJ!T$azH9Gz))k_oy8-TB3|nyF2e-l1dinB87bP9hR~eNq~ba9+>)+Oil)K#P8HbIp)H;&nW zskc>^&2KS?@VK#Bc2&55pZ9FDF&w#dDr86L&`7r^JbJ=*n1aZ3tl5`VJUtY9T4CJC*)?`g!Cc&;C-oGsDYjL#w_N`Y zUpr|DBCU$l9Han=_9WRSswJHLWR|cqyAzWcd8_15I7PFweC1p& z`=twtD|CQ^q5JFCoXnx}KvL5}W2*7e>xI{=-9FhD%Yo9#ty}?kp)~&ju%^)$(R_V} zrG#vv6!c@k2JwC#Hm59dj*ZOXvl;!|BiVWbt}7@DjZR=}bwqU^m)XTFGrSRob*iAd zMj%2&1ph-cm|^dvb;pw;zHF9IES@Ws8h5@3`5&xn3ioj48#Tf1#1N3lL-{ih1uGtK zfEUG{0SfTKw0U-eEv_Z=#4!0YdO(PC0Z-b*=ZEgdo?+nIP>#03kuV9>w${Dzf6yj( z@;MOrffJH)JP(_na%fj!;?1_+;!IZTlPNV0r6Ge)hH;)ZjqbBW-z5V!hj?=%3y%2G zlHDbVEMY&Yi4raP0!M9`yf~&#YcFosmo6qThRJ%Grnj?)z!N6hLq~VmXONaA#F;9o z>}b>14$B|GINyrS%`g-eBFR;|#8P|n5iUH*9d^G}%D$Xb6p&RmX|!DQb;_v>KjeL_ zzK#Ju#8vo3BD0=o-kKYDEs`yAj5JbR8x+98jT_Qf>GTd9z{0;Nc=s-g|H>9>YigF! ze;{*OseZieOjzg0`#1g9czBDg_K&#;+;Xec$+Le=_oYi_3`{DjSsihSffJ?R<0lSI zDK?%rXOAH_3Fv3TAIdekcaZ4v-LYZYxZ8qCAEO?xpl54;!q!RdZCL34bx%+aLqUuU zR3{slpEm?t0_x<)z!(Rtmm;g_-XszuNN;-W36GYJL9GtSR8=rtUu7ATBf&_%Q>}IJ zLy+x_`wz`Ws#gfN+Sck%cVggdIz((zp{52799M?X*t}$gJ1Ru&bf-FOU|6h#ky$n{dR>AXjCb3*fZA;w zut_u6?phyD%MQW9C)1UnT)&wE9SmHbpA0o@-f7J^)?ITT+j}w*ikl%6cw>Ixk0TY303Nbu1*8IbW?6|5PCW+3jVR)H zYs=-g7nEm6d4WeTcZ$q6Kgx+mQ#x0^{xgI|K*}ZO2P?5#cE+^O9-3(W`9($_t;rbe zBj_$;5o;)ugl*A5pJ$Hcf0KGmDZ#RfuX>%jn!>d-nL$a^L$J?>jN!;@w`nV2BS=H* zzAwr}G&K_o2%9sBmW!m*E5N1It#Pr852P|E8dQ#n1JKuRdtf=Cfg=7E^iI9>`T_ts zkK4~7DaAD|z{+?+yxsRD0Ht5Mm2X*I1{zy-HG3}#{EXo2spV}18}Ah4bZt<0L2UHtN|b={r|I-P`L-HWsvN_L4 z4n)a8hVfx!0P5ESB3TfDBU89qZt|QmEe-}EJb*lqlbHYh8_j?OK;?!2kue`Y^QesT zK?c%Y#Eo=={@YKD)_(CEzkXpa`1iHl-sfDScuJHeBUQsP3==K-u~hX<6b<(oaHSmC zB;S5B@rvi%OyBLnRWrBlibrc3<;c@pNVt2xc>b3A%!nSxh*NPo zIUY;MV#Y%v#c@*nn5P=QRU4Baf>@edTXVTwxN=WiOVIgD=XTyl42`j`qwKq%UPI3T z&w*%zJb6Jqa~=^lg*CZKs9zGDECk;}nLw;huqNQ0=$Y1miN-P0<~N;a#h=h;h8$DU z#4_DoLcfZ`*?HP|o7Nv!!J{>8RT57rcq^Ck*Edub+y>w$z#Md3LA3VO*C?%j%0$xK z%#@)NDl#4>4Wk-8x-y!IO^L%^iF`f8t<7D4al_1F=)i-2w&v*NI$cIb-f_pM@Jr zA81)OdihQ@zS?FZp!&a@&fVpKuZ70puiHJ;Ip8++u!Jnt(1?Dnh<>vB=8wNkZfi9c z@Il1$Pfi+={df~nbecn(z~1ZMKN;Z+SN;~#WAiow=r?Z!LWuyORLKwDrUb+MQi{iz@6&%p zd7(#SUu^5?R9~*~8T{am<W+^ut^;t=@&9@fjPS8>7T` z^H%Yn3*m+sN?-ptkg|bN!qi?^l!YjI@czkbl9OkhZq>KQ-x%2$r+K`@FAou_u)p?T zvw(vcxOHPNx}UUJBC&Kt97dU3O8Z5=7qC;~%tEMOG8#!RZbZ$A~Xptxgd>CW0V*fiP{GuflVtYc?5$ZE zt+6weJ(Gv`lHWRwf0F+B)MjG5@{Xk~`U>G$;dYevz{>69uW=1oKjXd?Y7|`tJ6b>H zF!+yVpC68KY+v#>&~uO5MrDEydT}oVA3}NY?m1m;VHQp8Kzpu0nhD)|p9Y&rXEd!X z_U51L`yLyok7ff+_lizZ5X|!J1~#9+OK7sa6vP>3e+)hj9LZ8oB4`5H0mdf;mp%lo zgc@c0;RxFX3!^ucjyz*MjLS(99dKX!!0KzdtIWilD?9#NuAcE*osFBRssjHouzU5Q z;Mz8if~trrYKxcGa#e#y^FYW=EpAXEd*g$4JsNg0MuN`&4rwwf%au5*qH((#8`>@ z_p8~4dcN!ZUMzplsaNjbkTt!WeRm=7r3Q)F9v88G>DPc>`CzEW_1aHY=YP`@+Y^PX zzKR3L{}V%i{Z^dhbJ2k5OM+N*knX_yjBa)s?fj5Bg;3t{*{eDq{58hZB=`dk8z_N< z!)<9=*VGWN)7)O#mlpnm&yc>Ib4hc^^bv(=FW1$L#jkry!9JV?m!X|izrvR?6oi$M z*D6j1IqE_o%9|4c{6c|@=N2I<>Mw{n1bhD z*5Wu(@M5;H%dDAeb$tZwZkEl&zxBr;De=v1&EzM^2;wd4&Jd2*8{<7cn+RqoCJY(y zp_o6gFy%-Wd?|G*N`&eD^$#qYQEj2>WU})&@ z$ZM1E#m7RC&o79*5QdO{=d?lOOO(|$Fu@JA#QW%GlfB~fkDg|I-FS8R zDD^;WJ?%iwQ2}DnC0!7iNjl;0m@c@cv6yzCY5wx_k>z1V=zh6HGK?7f6S2z=7+ze< z6{JKXoLc^HBCX)O?V|+BIioLXAwokCp~0YFXxf9io^24x52yZ#i5|PnH_%)hujZ=f4qt`#KP+&Z8l<(qHgv%T*1Ld=ux!k! z5zNI-oJ{0#@RWkc2-p5SU5p3XiCPq+(K|--O*Yi@#Gn73jOteM29{9h9kco63xBtl zIw0$5w^lr@&PA<3kLfoy;#RbJ$*kvYKg2NfQ~77vwnUqx_+cV52M1zaNDc&BJxkir zZ5TGLX$@l?y~+&WjqQwJ*Mv79;egIs9LUoLxq_@OGpqegq7kG!48Ej}ICvWK{+#$p z3P2S4a_2Ys*vjZ*Ip=>?%(i(;#vFJR&>-~pve^45!4voB3%Hi8gd+ZX!9H=I7CmOn zN?fUQ-D>WjMSz5|o?87SKal)&nKT^U760E_w^M?5M{wvJM&EcD%s*UEjal3)51P@O zTFc|C|E$DKYM%ntlWfGV|E-O3LN?&gyZS$LWlZ=DJwG}E-qt87D)<^e*0XbN5D?)6 z|6g0Ps0dt+LdYo~WGxyEOcWW2=5NygE#ShyZ`i<4Wyz&*DO-IO6hsTA(fG;d=!b*5 z`?_@`cwkNgqUxz9reCJqJjVpBCfcd!U1Y_)5wW!%zdZlu^tIQKg?Cuq@7B#dz<)UX zw(8(rC@GGAhmH+0Q3H(c!B66g8UJvrwTttnZVl%p+M80e5T=X>Q+KGgsXTR_v^ADp zO>Fkh3i}lz*&56w8L<=^KTVkXbW!^lvYcK5Cbi7)wMxnawbHraMHX7{7whL(0&bZG ziZ7-=EU7;KH=QJ`R9l@9k-&wxP5?3Okb?M=h5+FKCm&#ZPC+1lE|dvW&LgsPk++OR z6l>N?x;rj^6GIcfkb}|9286=x%k^hz5l>wOBWDPOv%uSCD>Doz9`1&|a3?Kuz3Ic* z8Nm@ueU?@$y~6Ba=84gT7p4Cyh#hIi@qaYKOD(h~2laCqeA6Nubaa?p z7d%_{;X-w+sQS`|T2;Y$TAqW|zGOY%HOwA1u#F~Ki^aV%(s_I(N@yr%q z=47Kk(H~0vy5Ey57h{r-HK}Y<@?NT(`*i;sYD~mb-=LhR9CqerP9yTCUzTes)7Phu zwxbUov$fN7H(hT3Z8_Js?$VkGJRr&WONQ4AdH@K0dM(~FSywC$c zUIoOi+I{D~3m3Qb!6&cGcg7JLS-@Spy@S~fKYg0>G=y*H>K#Xl()2g)1Qx6=?h;&u zLp|6(Fl@F1;}60NRC`9?%Y?;yx=)vZ8@_-vSLko9+*7z9QWd!VmqpivE~c1+9j5uU zSptdkpe?~3-fsxggCmx-lRp|osdlf!{;Tx4$}das*ZE)tv?sOg80ExHQT&hyreb`) z>dD1Q^j%?J6ryf55KCo)uq+j+2Ovmqo)0d3;C3fe%iuUkMJd#K96Y-+^S~gN4YhO3 zo7n_6zwsG!W%|aWPHAS;L&(1dmvw;6{q759onkfPprRVN_on%d=+oOc)^0UCS*{*( zG%@Cd=wq*_x56ttRd#hW6BB)py+WrM2#pJyew=t6hes_W`Q_*!%EZGjx1P48<1f;| zp~MlAet}ZWO20P9W9dW|j=1bZzHf)&?YI_1t_q3$;Nq3Kp$DR@0aNz_reKmE8xC(8 zpY~P9A5;0IHf0=W*-UEHC29$BWCm{I792>uNd)?zgNORI++W|2d6VBgCIjECA|vf5 z(HY(by2&IR4@n~$VFf-r!)Z@xdi-N%eETVe)vE_L*HQ=QpB7FuUe}qw#%~$v2weI{ zN?qI(DI!mOd^YoO&HKuZjfJ`2Snp%(4h5u|-bb3B!lra^tJW`oT(u*I0aBF6`$!E5 z9!nwjR}gc4Pd0zq<4^DvA;DJ)U!u1%5L$7dB;dKj-B(+)@vVu`XHXA2j|s*1)6O!x;X39!h!IPn23pB>bQC zy%oNDSf8QLz`I+<7s?19Gy3@yxdnKZxd8^F43VM5WK;ANJI#9ZPZwP#c2)m>ABC(bq6iq{p2B6DH9lY#&Fn0KSBQC zRV3hYaP=9X(K0i_%zYA90|f}2rP_2(4u5BUlb-gZh%p=(GX{Bg+R+rzr(50p^h0Sa zft~R5p%Br6d^Ul+LT9iFMd=>r@0t09hvm}w;^U|X7j7^kRh0@=`}eS>JLgnp?G9Hj zkJ*oO@=vmnR~WB7UgnBo3jAa$)>Of>ubmkKIP}x&Ua;ob-v;%|Ajll{)8=@ZvQ!XC zRZ;b+k@=%t0hTVehra5MVwW$STb!42wAP@BkyQKOXx3M_`K;!_OQ4dXpIu~GEMgE> zR35V57Z~^^J$uJw#MgmoAn4V(W))4j<=?3#T%R8CmAD{i&R?c}YM`p7+>iZ!uBg$W zT5oK_k53o6f}lh0>+f8#b`Sq9tn^-qsVSpQJD8&4G?`jpKgHY1LA~YZQ=x}dkMAGX zwX!H#Xj-^+Hqs^WP;zzOdENwm8uhU3gj+1QoSKWEM=r^nl}h{wSuWqweoe88q+w*X zcPeLiiRebC3uat7VQ%=zE^0&P0(;rcM#(!`!n;g9PIBoAxt|8-$KfN(uv*T7B(j>o@yl4F(b9 z&Y8P3s4UN#QI5_>zG0&|2I`BFQZ>zSh<-(ge!Xlwm>rED)T+-oD?R)w^(V!%Na%$Fi{ui#O>-#(4^Gf2P_(k$RD*hjbB#Ysn__kwGokh=P z@DsKA{>3O+jHoxQ&uHcLRJAw;P^kS&mSG9#cHt%3(dB9o{~;v)_^F{QXZiadx*lnW z-6CQ9zJR8ds0KrS#rtN8_5!)GFFUMuksW1FjoElg8p>5O;({QeLml} z1w*#0hI8eiW-0aO{WX@38XF? zP!E@lhEvhoI}!_x(DS`PU9cK%NjXI!ImO@kfRO#8ZO!huJW-)SoWEi# z{`c|8#IF>~%+3Bz&zXoH<*9VLb3y98)Dff}hHypGx1YzUC)ydFTs8sSdImp{(irHG z`u&Bxl)i2l|KO(u(TEG$dk0c%G@_ngQDG@kA^Ivo=dBrMlxYq?nqU->DC{oM= zdF$BMZHH8iJ?mdvkzgzCR<&`1W_kG4v5XM3V$h`*|Dg-%S@8v`iR5F}{|F#ionKzr zKqy0|dSyl6%lSfEh>m2cJlxJq5opz#W%YlUBA#HxFGjC8M$M7iQ%F7c<32p1bxx*@{!)t^Em{!Wbl&jq$Zk-XhQ)4Oi!5z=0ipj8lAo%>uuEVtB*R7xXbSW{@Lqx+@L5xYmD|;|rc?7s0!X_~F~{<9e!rIF7XT!I}dw6(i*C6i-^Dl%W(p ziP6{x!3Ot!h#gA7mj@c=#3ly$>aDbY!s)YOy@6!MGUUsjCl{fsi|w{5lhm)ser%Q< zrnqC6TwqbZ5bi)}omtZOPN)6;cM97s8PkT}hl%(^hbO-3YtfgA&NW~Z4o^7AQSe=k zW~o)zuin{rOueBJTyEtX6uJ0B)pEC$n-d5Ae0G}^ZXmTj|Ks!K z{oylpa&1%2=4yr37A@)QJBAl!+6h7;&0k1YO}9?0^9CdHgJWCf^PI)NR))I%QBkW2IF5 zAP+fixMEtAlV3dWUDp2s^xXNS@V;KFS+5a9UD9LknzH!HDP64WR4B`}_4gjimc}o4 zKfLP&6KYvAn(X$Y0Xvf_MDt523(q;s#~CNG$Tu7vPK>gcg*e#lCbIK-tk{;8AX@SMHj65mXrz6x!8p>v?@pQE1xv*1v>va6)ONj&~EN)^+ zxcK;1XKzx5SLT3bqB*=j5`SOcrQSEWz~hRwYu3*}-M1PRF6oH@Y$reI?ljzbU8|eA zZ1ohy`J}fDB6>}ZO&iXxi}LL8w1z)2&Pfj$DKvIuelK;8-@y{BCdQ0PpLlv64gWTp zd}UMHf?nnE{ixf*NTX%m_Lm-j+(ck$o}rW21Pf@YHN$BZv1IDbJ|$@ JxfbEZ{{nU;xD5aR literal 0 HcmV?d00001 diff --git a/docs-en/chapter_hashing/hash_map.assets/hash_function.png b/docs-en/chapter_hashing/hash_map.assets/hash_function.png new file mode 100644 index 0000000000000000000000000000000000000000..d89389c2132b06f7b28d8ab0d600800860a6fdba GIT binary patch literal 33971 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%0D&5iQTdvKb@W>^LVTvD9Id1e7`4*p@Z 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ͤkH3r9U;+&_ra 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 literal 0 HcmV?d00001 diff --git a/docs-en/chapter_hashing/hash_map.assets/hash_table_reshash.png b/docs-en/chapter_hashing/hash_map.assets/hash_table_reshash.png new file mode 100644 index 0000000000000000000000000000000000000000..c00f1c20ece3f05ddcb7401c2f48ff7b0cc8e950 GIT binary patch literal 27971 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

uS%vqgersOs6$ya7MXNU0gcH<$ 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 literal 0 HcmV?d00001 diff --git a/docs-en/chapter_hashing/hash_map.md b/docs-en/chapter_hashing/hash_map.md new file mode 100755 index 000000000..6a7e47722 --- /dev/null +++ b/docs-en/chapter_hashing/hash_map.md @@ -0,0 +1,525 @@ +# Hash Table + +A "hash table", also known as a "hash map", achieves efficient element querying by establishing a mapping between keys and values. Specifically, when we input a `key` into the hash table, we can retrieve the corresponding `value` in $O(1)$ time. + +As shown in the figure below, given $n$ students, each with two pieces of data: "name" and "student number". If we want to implement a query feature that returns the corresponding name when given a student number, we can use the hash table shown in the figure below. + +![Abstract representation of a hash table](hash_map.assets/hash_table_lookup.png) + +Apart from hash tables, arrays and linked lists can also be used to implement querying functions. Their efficiency is compared in the table below. + +- **Adding Elements**: Simply add the element to the end of the array (or linked list), using $O(1)$ time. +- **Querying Elements**: Since the array (or linked list) is unordered, it requires traversing all the elements, using $O(n)$ time. +- **Deleting Elements**: First, locate the element, then delete it from the array (or linked list), using $O(n)$ time. + +

Table   Comparison of Element Query Efficiency

+ +| | Array | Linked List | Hash Table | +| -------------- | ------ | ----------- | ---------- | +| Find Element | $O(n)$ | $O(n)$ | $O(1)$ | +| Add Element | $O(1)$ | $O(1)$ | $O(1)$ | +| Delete Element | $O(n)$ | $O(n)$ | $O(1)$ | + +Observations reveal that **the time complexity for adding, deleting, and querying in a hash table is $O(1)$**, which is highly efficient. + +## Common Operations of Hash Table + +Common operations of a hash table include initialization, querying, adding key-value pairs, and deleting key-value pairs, etc. Example code is as follows: + +=== "Python" + + ```python title="hash_map.py" + # Initialize hash table + hmap: dict = {} + + # Add operation + # Add key-value pair (key, value) to the hash table + hmap[12836] = "Xiao Ha" + hmap[15937] = "Xiao Luo" + hmap[16750] = "Xiao Suan" + hmap[13276] = "Xiao Fa" + hmap[10583] = "Xiao Ya" + + # Query operation + # Input key into hash table, get value + name: str = hmap[15937] + + # Delete operation + # Delete key-value pair (key, value) from hash table + hmap.pop(10583) + ``` + +=== "C++" + + ```cpp title="hash_map.cpp" + /* Initialize hash table */ + unordered_map map; + + /* Add operation */ + // Add key-value pair (key, value) to the hash table + map[12836] = "Xiao Ha"; + map[15937] = "Xiao Luo"; + map[16750] = "Xiao Suan"; + map[13276] = "Xiao Fa"; + map[10583] = "Xiao Ya"; + + /* Query operation */ + // Input key into hash table, get value + string name = map[15937]; + + /* Delete operation */ + // Delete key-value pair (key, value) from hash table + map.erase(10583); + ``` + +=== "Java" + + ```java title="hash_map.java" + /* Initialize hash table */ + Map map = new HashMap<>(); + + /* Add operation */ + // Add key-value pair (key, value) to the hash table + map.put(12836, "Xiao Ha"); + map.put(15937, "Xiao Luo"); + map.put(16750, "Xiao Suan"); + map.put(13276, "Xiao Fa"); + map.put(10583, "Xiao Ya"); + + /* Query operation */ + // Input key into hash table, get value + String name = map.get(15937); + + /* Delete operation */ + // Delete key-value pair (key, value) from hash table + map.remove(10583); + ``` + +=== "C#" + + ```csharp title="hash_map.cs" + /* Initialize hash table */ + Dictionary map = new() { + /* Add operation */ + // Add key-value pair (key, value) to the hash table + { 12836, "Xiao Ha" }, + { 15937, "Xiao Luo" }, + { 16750, "Xiao Suan" }, + { 13276, "Xiao Fa" }, + { 10583, "Xiao Ya" } + }; + + /* Query operation */ + // Input key into hash table, get value + string name = map[15937]; + + /* Delete operation */ + // Delete key-value pair (key, value) from hash table + map.Remove(10583); + ``` + +=== "Go" + + ```go title="hash_map_test.go" + /* Initialize hash table */ + hmap := make(map[int]string) + + /* Add operation */ + // Add key-value pair (key, value) to the hash table + hmap[12836] = "Xiao Ha" + hmap[15937] = "Xiao Luo" + hmap[16750] = "Xiao Suan" + hmap[13276] = "Xiao Fa" + hmap[10583] = "Xiao Ya" + + /* Query operation */ + // Input key into hash table, get value + name := hmap[15937] + + /* Delete operation */ + // Delete key-value pair (key, value) from hash table + delete(hmap, 10583) + ``` + +=== "Swift" + + ```swift title="hash_map.swift" + /* Initialize hash table */ + var map: [Int: String] = [:] + + /* Add operation */ + // Add key-value pair (key, value) to the hash table + map[12836] = "Xiao Ha" + map[15937] = "Xiao Luo" + map[16750] = "Xiao Suan" + map[13276] = "Xiao Fa" + map[10583] = "Xiao Ya" + + /* Query operation */ + // Input key into hash table, get value + let name = map[15937]! + + /* Delete operation */ + // Delete key-value pair (key, value) from hash table + map.removeValue(forKey: 10583) + ``` + +=== "JS" + + ```javascript title="hash_map.js" + /* Initialize hash table */ + const map = new Map(); + /* Add operation */ + // Add key-value pair (key, value) to the hash table + map.set(12836, 'Xiao Ha'); + map.set(15937, 'Xiao Luo'); + map.set(16750, 'Xiao Suan'); + map.set(13276, 'Xiao Fa'); + map.set(10583, 'Xiao Ya'); + + /* Query operation */ + // Input key into hash table, get value + let name = map.get(15937); + + /* Delete operation */ + // Delete key-value pair (key, value) from hash table + map.delete(10583); + ``` + +=== "TS" + + ```typescript title="hash_map.ts" + /* Initialize hash table */ + const map = new Map(); + /* Add operation */ + // Add key-value pair (key, value) to the hash table + map.set(12836, 'Xiao Ha'); + map.set(15937, 'Xiao Luo'); + map.set(16750, 'Xiao Suan'); + map.set(13276, 'Xiao Fa'); + map.set(10583, 'Xiao Ya'); + console.info('\nAfter adding, the hash table is\nKey -> Value'); + console.info(map); + + /* Query operation */ + // Input key into hash table, get value + let name = map.get(15937); + console.info('\nInput student number 15937, query name ' + name); + + /* Delete operation */ + // Delete key-value pair (key, value) from hash table + map.delete(10583); + console.info('\nAfter deleting 10583, the hash table is\nKey -> Value'); + console.info(map); + ``` + +=== "Dart" + + ```dart title="hash_map.dart" + /* Initialize hash table */ + Map map = {}; + + /* Add operation */ + // Add key-value pair (key, value) to the hash table + map[12836] = "Xiao Ha"; + map[15937] = "Xiao Luo"; + map[16750] = "Xiao Suan"; + map[13276] = "Xiao Fa"; + map[10583] = "Xiao Ya"; + + /* Query operation */ + // Input key into hash table, get value + String name = map[15937]; + + /* Delete operation */ + // Delete key-value pair (key, value) from hash table + map.remove(10583); + ``` + +=== "Rust" + + ```rust title="hash_map.rs" + use std::collections::HashMap; + + /* Initialize hash table */ + let mut map: HashMap = HashMap::new(); + + /* Add operation */ + // Add key-value pair (key, value) to the hash table + map.insert(12836, "Xiao Ha".to_string()); + map.insert(15937, "Xiao Luo".to_string()); + map.insert(16750, "Xiao Suan".to_string()); + map.insert(13279, "Xiao Fa".to_string()); + map.insert(10583, "Xiao Ya".to_string()); + + /* Query operation */ + // Input key into hash table, get value + let _name: Option<&String> = map.get(&15937); + + /* Delete operation */ + // Delete key-value pair (key, value) from hash table + let _removed_value: Option = map.remove(&10583); + ``` + +=== "C" + + ```c title="hash_map.c" + // C does not provide a built-in hash table + ``` + +=== "Zig" + + ```zig title="hash_map.zig" + + ``` + +??? pythontutor "Code Visualization" + + 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%E6%9F%A5%E8%AF%A2%E6%93%8D%E4%BD%9C%0A%20%20%20%20%23%20%E5%90%91%E5%93%88%E5%B8%8C%E8%A1%A8%E4%B8%AD%E8%BE%93%E5%85%A5%E9%94%AE%20key%20%EF%BC%8C%E5%BE%97%E5%88%B0%E5%80%BC%20value%0A%20%20%20%20name%20%3D%20hmap%5B15937%5D%0A%20%20%20%20%0A%20%20%20%20%23%20%E5%88%A0%E9%99%A4%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%E5%88%A0%E9%99%A4%E9%94%AE%E5%80%BC%E5%AF%B9%20%28key,%20value%29%0A%20%20%20%20hmap.pop%2810583%29&cumulative=false&curInstr=2&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=311&rawInputLstJSON=%5B%5D&textReferences=false + +There are three common ways to traverse a hash table: traversing key-value pairs, keys, and values. Example code is as follows: + +=== "Python" + + ```python title="hash_map.py" + # Traverse hash table + # Traverse key-value pairs key->value + for key, value in hmap.items(): + print(key, "->", value) + # Traverse keys only + for key in hmap.keys(): + print(key) + # Traverse values only + for value in hmap.values(): + print(value) + ``` + +=== "C++" + + ```cpp title="hash_map.cpp" + /* Traverse hash table */ + // Traverse key-value pairs key->value + for (auto kv: map) { + cout << kv.first << " -> " << kv.second << endl; + } + // Traverse using iterator key->value + for (auto iter = map.begin(); iter != map.end(); iter++) { + cout << iter->first << "->" << iter->second << endl; + } + ``` + +=== "Java" + + ```java title="hash_map.java" + /* Traverse hash table */ + // Traverse key-value pairs key->value + for (Map.Entry kv: map.entrySet()) { + System.out.println(kv.getKey() + " -> " + kv.getValue()); + } + // Traverse keys only + for (int key: map.keySet()) { + System.out.println(key); + } + // Traverse values only + for (String val: map.values()) { + System.out.println(val); + } + ``` + +=== "C#" + + ```csharp title="hash_map.cs" + /* Traverse hash table */ + // Traverse key-value pairs Key->Value + foreach (var kv in map) { + Console.WriteLine(kv.Key + " -> " + kv.Value); + } + // Traverse keys only + foreach (int key in map.Keys) { + Console.WriteLine(key); + } + // Traverse values only + foreach (string val in map.Values) { + Console.WriteLine(val); + } + ``` + +=== "Go" + + ```go title="hash_map_test.go" + /* Traverse hash table */ + // Traverse key-value pairs key->value + for key, value := range hmap { + fmt.Println(key, "->", value) + } + // Traverse keys only + for key := range hmap { + fmt.Println(key) + } + // Traverse values only + for _, value := range hmap { + fmt.Println(value) + } + ``` + +=== "Swift" + + ```swift title="hash_map.swift" + /* Traverse hash table */ + // Traverse key-value pairs Key->Value + for (key, value) in map { + print("\(key) -> \(value)") + } + // Traverse keys only + for key in map.keys { + print(key) + } + // Traverse values only + for value in map.values { + print(value) + } + ``` + +=== "JS" + + ```javascript title="hash_map.js" + /* Traverse hash table */ + console.info('\nTraverse key-value pairs Key->Value'); + for (const [k, v] of map.entries()) { + console.info(k + ' -> ' + v); + } + console.info('\nTraverse keys only Key'); + for (const k of map.keys()) { + console.info(k); + } + console.info('\nTraverse values only Value'); + for (const v of map.values()) { + console.info(v); + } + ``` + +=== "TS" + + ```typescript title="hash_map.ts" + /* Traverse hash table */ + console.info('\nTraverse key-value pairs Key->Value'); + for (const [k, v] of map.entries()) { + console.info(k + ' -> ' + v); + } + console.info('\nTraverse keys only Key'); + for (const k of map.keys()) { + console.info(k); + } + console.info('\nTraverse values only Value'); + for (const v of map.values()) { + console.info(v); + } + ``` + +=== "Dart" + + ```dart title="hash_map.dart" + /* Traverse hash table */ + // Traverse key-value pairs Key->Value + map.forEach((key, value) { + print('$key -> $value'); + }); + + // Traverse keys only Key + map.keys.forEach((key) { + print(key); + }); + + // Traverse values only Value + map.values.forEach((value) { + print(value); + }); + ``` + +=== "Rust" + + ```rust title="hash_map.rs" + /* Traverse hash table */ + // Traverse key-value pairs Key->Value + for (key, value) in &map { + println!("{key} -> {value}"); + } + + // Traverse keys only Key + for key in map.keys() { + println!("{key}"); + } + + // Traverse values only Value + for value in map.values() { + println!("{value}"); + } + ``` + +=== "C" + + ```c title="hash_map.c" + // C does not provide a built-in hash table + ``` + +=== "Zig" + + ```zig title="hash_map.zig" + // Zig example is not provided + ``` + +??? pythontutor "Code Visualization" + + 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 Implementation of Hash Table + +First, let's consider the simplest case: **implementing a hash table using just an array**. In the hash table, each empty slot in the array is called a "bucket", and each bucket can store one key-value pair. Therefore, the query operation involves finding the bucket corresponding to the `key` and retrieving the `value` from it. + +So, how do we locate the appropriate bucket based on the `key`? This is achieved through a "hash function". The role of the hash function is to map a larger input space to a smaller output space. In a hash table, the input space is all possible keys, and the output space is all buckets (array indices). In other words, input a `key`, **and we can use the hash function to determine the storage location of the corresponding key-value pair in the array**. + +The calculation process of the hash function for a given `key` is divided into the following two steps: + +1. Calculate the hash value using a certain hash algorithm `hash()`. +2. Take the modulus of the hash value with the number of buckets (array length) `capacity` to obtain the array index `index`. + +```shell +index = hash(key) % capacity +``` + +Afterward, we can use `index` to access the corresponding bucket in the hash table and thereby retrieve the `value`. + +Assuming array length `capacity = 100` and hash algorithm `hash(key) = key`, the hash function is `key % 100`. The figure below uses `key` as the student number and `value` as the name to demonstrate the working principle of the hash function. + +![Working principle of hash function](hash_map.assets/hash_function.png) + +The following code implements a simple hash table. Here, we encapsulate `key` and `value` into a class `Pair` to represent the key-value pair. + +```src +[file]{array_hash_map}-[class]{array_hash_map}-[func]{} +``` + +## Hash Collision and Resizing + +Fundamentally, the role of the hash function is to map the entire input space of all keys to the output space of all array indices. However, the input space is often much larger than the output space. Therefore, **theoretically, there must be situations where "multiple inputs correspond to the same output"**. + +For the hash function in the above example, if the last two digits of the input `key` are the same, the output of the hash function will also be the same. For example, when querying for students with student numbers 12836 and 20336, we find: + +```shell +12836 % 100 = 36 +20336 % 100 = 36 +``` + +As shown in the figure below, both student numbers point to the same name, which is obviously incorrect. This situation where multiple inputs correspond to the same output is known as "hash collision". + +![Example of hash collision](hash_map.assets/hash_collision.png) + +It is easy to understand that the larger the capacity $n$ of the hash table, the lower the probability of multiple keys being allocated to the same bucket, and the fewer the collisions. Therefore, **expanding the capacity of the hash table can reduce hash collisions**. + +As shown in the figure below, before expansion, key-value pairs `(136, A)` and `(236, D)` collided; after expansion, the collision is resolved. + +![Hash table expansion](hash_map.assets/hash_table_reshash.png) + +Similar to array expansion, resizing a hash table requires migrating all key-value pairs from the original hash table to the new one, which is time-consuming. Furthermore, since the capacity `capacity` of the hash table changes, we need to recalculate the storage positions of all key-value pairs using the hash function, which adds to the computational overhead of the resizing process. Therefore, programming languages often reserve a sufficiently large capacity for the hash table to prevent frequent resizing. + +The "load factor" is an important concept for hash tables. It is defined as the ratio of the number of elements in the hash table to the number of buckets. It is used to measure the severity of hash collisions and **is often used as a trigger for resizing the hash table**. For example, in Java, when the load factor exceeds $0.75$, the system will resize the hash table to twice its original size. diff --git a/docs-en/chapter_hashing/index.md b/docs-en/chapter_hashing/index.md new file mode 100644 index 000000000..c65d9495d --- /dev/null +++ b/docs-en/chapter_hashing/index.md @@ -0,0 +1,13 @@ +# Hash Table + +
+ +![Hash Table](../assets/covers/chapter_hashing.jpg) + +
+ +!!! abstract + + In the world of computing, a hash table is like a wise librarian. + + He knows how to calculate index numbers, allowing it to quickly locate the target book. diff --git a/docs-en/chapter_hashing/summary.md b/docs-en/chapter_hashing/summary.md new file mode 100644 index 000000000..fae506e09 --- /dev/null +++ b/docs-en/chapter_hashing/summary.md @@ -0,0 +1,47 @@ +# Summary + +### 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. +- The hash function maps a `key` to an array index, allowing access to the corresponding bucket to retrieve the `value`. +- Two different keys may end up with the same array index after hashing, leading to erroneous query results. This phenomenon is known as hash collision. +- The larger the capacity of the hash table, the lower the probability of hash collisions. Therefore, hash table resizing can mitigate hash collisions. Similar to array resizing, hash table resizing is costly. +- Load factor, defined as the ratio of the number of elements to the number of buckets in the hash table, reflects the severity of hash collisions and is often used as a trigger for resizing the hash table. +- Chaining addresses hash collisions by converting each element into a linked list, storing all colliding elements in the same list. However, excessively long lists can reduce query efficiency, which can be improved by converting the lists into red-black trees. +- Open addressing handles hash collisions through multiple probes. Linear probing uses a fixed step size but cannot delete elements and is prone to clustering. Multiple hashing uses several hash functions for probing, making it less susceptible to clustering but increasing computational load. +- Different programming languages adopt various hash table implementations. For example, Java's `HashMap` uses chaining, while Python's `dict` employs open addressing. +- In hash tables, we desire hash algorithms with determinism, high efficiency, and uniform distribution. In cryptography, hash algorithms should also possess collision resistance and the avalanche effect. +- Hash algorithms typically use large prime numbers as moduli to ensure uniform distribution of hash values and reduce hash collisions. +- Common hash algorithms include MD5, SHA-1, SHA-2, and SHA-3. MD5 is often used for file integrity checks, while SHA-2 is commonly used in secure applications and protocols. +- Programming languages usually provide built-in hash algorithms for data types to calculate bucket indices in hash tables. Generally, only immutable objects are hashable. + +### Q & A + +**Q**: When does the time complexity of a hash table degrade to $O(n)$? + +The time complexity of a hash table can degrade to $O(n)$ when hash collisions are severe. When the hash function is well-designed, the capacity is set appropriately, and collisions are evenly distributed, the time complexity is $O(1)$. We usually consider the time complexity to be $O(1)$ when using built-in hash tables in programming languages. + +**Q**: Why not use the hash function $f(x) = x$? This would eliminate collisions. + +Under the hash function $f(x) = x$, each element corresponds to a unique bucket index, which is equivalent to an array. However, the input space is usually much larger than the output space (array length), so the last step of a hash function is often to take the modulo of the array length. In other words, the goal of a hash table is to map a larger state space to a smaller one while providing $O(1)$ query efficiency. + +**Q**: Why can hash tables be more efficient than arrays, linked lists, or binary trees, even though they are implemented using these structures? + +Firstly, hash tables have higher time efficiency but lower space efficiency. A significant portion of memory in hash tables remains unused. + +Secondly, they are only more efficient in specific use cases. If a feature can be implemented with the same time complexity using an array or a linked list, it's usually faster than using a hash table. This is because the computation of the hash function incurs overhead, making the constant factor in the time complexity larger. + +Lastly, the time complexity of hash tables can degrade. For example, in chaining, we perform search operations in a linked list or red-black tree, which still risks degrading to $O(n)$ time. + +**Q**: Does multiple hashing also have the flaw of not being able to delete elements directly? Can space marked as deleted be reused? + +Multiple hashing is a form of open addressing, and all open addressing methods have the drawback of not being able to delete elements directly; they require marking elements as deleted. Marked spaces can be reused. When inserting new elements into the hash table, and the hash function points to a position marked as deleted, that position can be used by the new element. This maintains the probing sequence of the hash table while ensuring efficient use of space. + +**Q**: Why do hash collisions occur during the search process in linear probing? + +During the search process, the hash function points to the corresponding bucket and key-value pair. If the `key` doesn't match, it indicates a hash collision. Therefore, linear probing will search downwards at a predetermined step size until the correct key-value pair is found or the search fails. + +**Q**: Why can resizing a hash table alleviate hash collisions? + +The last step of a hash function often involves taking the modulo of the array length $n$, to keep the output within the array index range. When resizing, the array length $n$ changes, and the indices corresponding to the keys may also change. Keys that were previously mapped to the same bucket might be distributed across multiple buckets after resizing, thereby mitigating hash collisions. diff --git a/docs-en/chapter_stack_and_queue/deque.md b/docs-en/chapter_stack_and_queue/deque.md index ec9d0eb0b..367a0d586 100644 --- a/docs-en/chapter_stack_and_queue/deque.md +++ b/docs-en/chapter_stack_and_queue/deque.md @@ -330,7 +330,7 @@ Similarly, we can directly use the double-ended queue classes implemented in pro ``` -??? pythontutor "Visualizing Code" +??? pythontutor "Code Visualization" https://pythontutor.com/render.html#code=from%20collections%20import%20deque%0A%0A%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%8F%8C%E5%90%91%E9%98%9F%E5%88%97%0A%20%20%20%20deq%20%3D%20deque%28%29%0A%0A%20%20%20%20%23%20%E5%85%83%E7%B4%A0%E5%85%A5%E9%98%9F%0A%20%20%20%20deq.append%282%29%20%20%23%20%E6%B7%BB%E5%8A%A0%E8%87%B3%E9%98%9F%E5%B0%BE%0A%20%20%20%20deq.append%285%29%0A%20%20%20%20deq.append%284%29%0A%20%20%20%20deq.appendleft%283%29%20%20%23%20%E6%B7%BB%E5%8A%A0%E8%87%B3%E9%98%9F%E9%A6%96%0A%20%20%20%20deq.appendleft%281%29%0A%20%20%20%20print%28%22%E5%8F%8C%E5%90%91%E9%98%9F%E5%88%97%20deque%20%3D%22,%20deq%29%0A%0A%20%20%20%20%23%20%E8%AE%BF%E9%97%AE%E5%85%83%E7%B4%A0%0A%20%20%20%20front%20%3D%20deq%5B0%5D%20%20%23%20%E9%98%9F%E9%A6%96%E5%85%83%E7%B4%A0%0A%20%20%20%20print%28%22%E9%98%9F%E9%A6%96%E5%85%83%E7%B4%A0%20front%20%3D%22,%20front%29%0A%20%20%20%20rear%20%3D%20deq%5B-1%5D%20%20%23%20%E9%98%9F%E5%B0%BE%E5%85%83%E7%B4%A0%0A%20%20%20%20print%28%22%E9%98%9F%E5%B0%BE%E5%85%83%E7%B4%A0%20rear%20%3D%22,%20rear%29%0A%0A%20%20%20%20%23%20%E5%85%83%E7%B4%A0%E5%87%BA%E9%98%9F%0A%20%20%20%20pop_front%20%3D%20deq.popleft%28%29%20%20%23%20%E9%98%9F%E9%A6%96%E5%85%83%E7%B4%A0%E5%87%BA%E9%98%9F%0A%20%20%20%20print%28%22%E9%98%9F%E9%A6%96%E5%87%BA%E9%98%9F%E5%85%83%E7%B4%A0%20%20pop_front%20%3D%22,%20pop_front%29%0A%20%20%20%20print%28%22%E9%98%9F%E9%A6%96%E5%87%BA%E9%98%9F%E5%90%8E%20deque%20%3D%22,%20deq%29%0A%20%20%20%20pop_rear%20%3D%20deq.pop%28%29%20%20%23%20%E9%98%9F%E5%B0%BE%E5%85%83%E7%B4%A0%E5%87%BA%E9%98%9F%0A%20%20%20%20print%28%22%E9%98%9F%E5%B0%BE%E5%87%BA%E9%98%9F%E5%85%83%E7%B4%A0%20%20pop_rear%20%3D%22,%20pop_rear%29%0A%20%20%20%20print%28%22%E9%98%9F%E5%B0%BE%E5%87%BA%E9%98%9F%E5%90%8E%20deque%20%3D%22,%20deq%29%0A%0A%20%20%20%20%23%20%E8%8E%B7%E5%8F%96%E5%8F%8C%E5%90%91%E9%98%9F%E5%88%97%E7%9A%84%E9%95%BF%E5%BA%A6%0A%20%20%20%20size%20%3D%20len%28deq%29%0A%20%20%20%20print%28%22%E5%8F%8C%E5%90%91%E9%98%9F%E5%88%97%E9%95%BF%E5%BA%A6%20size%20%3D%22,%20size%29%0A%0A%20%20%20%20%23%20%E5%88%A4%E6%96%AD%E5%8F%8C%E5%90%91%E9%98%9F%E5%88%97%E6%98%AF%E5%90%A6%E4%B8%BA%E7%A9%BA%0A%20%20%20%20is_empty%20%3D%20len%28deq%29%20%3D%3D%200%0A%20%20%20%20print%28%22%E5%8F%8C%E5%90%91%E9%98%9F%E5%88%97%E6%98%AF%E5%90%A6%E4%B8%BA%E7%A9%BA%20%3D%22,%20is_empty%29&cumulative=false&curInstr=3&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=311&rawInputLstJSON=%5B%5D&textReferences=false diff --git a/docs-en/chapter_stack_and_queue/queue.md b/docs-en/chapter_stack_and_queue/queue.md index c41d0d2b0..c0dcb90ae 100755 --- a/docs-en/chapter_stack_and_queue/queue.md +++ b/docs-en/chapter_stack_and_queue/queue.md @@ -308,7 +308,7 @@ We can directly use the ready-made queue classes in programming languages: ``` -??? pythontutor "Visualizing Code" +??? pythontutor "Code Visualization" https://pythontutor.com/render.html#code=from%20collections%20import%20deque%0A%0A%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%E9%98%9F%E5%88%97%0A%20%20%20%20%23%20%E5%9C%A8%20Python%20%E4%B8%AD%EF%BC%8C%E6%88%91%E4%BB%AC%E4%B8%80%E8%88%AC%E5%B0%86%E5%8F%8C%E5%90%91%E9%98%9F%E5%88%97%E7%B1%BB%20deque%20%E7%9C%8B%E4%BD%9C%E9%98%9F%E5%88%97%E4%BD%BF%E7%94%A8%0A%20%20%20%20%23%20%E8%99%BD%E7%84%B6%20queue.Queue%28%29%20%E6%98%AF%E7%BA%AF%E6%AD%A3%E7%9A%84%E9%98%9F%E5%88%97%E7%B1%BB%EF%BC%8C%E4%BD%86%E4%B8%8D%E5%A4%AA%E5%A5%BD%E7%94%A8%0A%20%20%20%20que%20%3D%20deque%28%29%0A%0A%20%20%20%20%23%20%E5%85%83%E7%B4%A0%E5%85%A5%E9%98%9F%0A%20%20%20%20que.append%281%29%0A%20%20%20%20que.append%283%29%0A%20%20%20%20que.append%282%29%0A%20%20%20%20que.append%285%29%0A%20%20%20%20que.append%284%29%0A%20%20%20%20print%28%22%E9%98%9F%E5%88%97%20que%20%3D%22,%20que%29%0A%0A%20%20%20%20%23%20%E8%AE%BF%E9%97%AE%E9%98%9F%E9%A6%96%E5%85%83%E7%B4%A0%0A%20%20%20%20front%20%3D%20que%5B0%5D%0A%20%20%20%20print%28%22%E9%98%9F%E9%A6%96%E5%85%83%E7%B4%A0%20front%20%3D%22,%20front%29%0A%0A%20%20%20%20%23%20%E5%85%83%E7%B4%A0%E5%87%BA%E9%98%9F%0A%20%20%20%20pop%20%3D%20que.popleft%28%29%0A%20%20%20%20print%28%22%E5%87%BA%E9%98%9F%E5%85%83%E7%B4%A0%20pop%20%3D%22,%20pop%29%0A%20%20%20%20print%28%22%E5%87%BA%E9%98%9F%E5%90%8E%20que%20%3D%22,%20que%29%0A%0A%20%20%20%20%23%20%E8%8E%B7%E5%8F%96%E9%98%9F%E5%88%97%E7%9A%84%E9%95%BF%E5%BA%A6%0A%20%20%20%20size%20%3D%20len%28que%29%0A%20%20%20%20print%28%22%E9%98%9F%E5%88%97%E9%95%BF%E5%BA%A6%20size%20%3D%22,%20size%29%0A%0A%20%20%20%20%23%20%E5%88%A4%E6%96%AD%E9%98%9F%E5%88%97%E6%98%AF%E5%90%A6%E4%B8%BA%E7%A9%BA%0A%20%20%20%20is_empty%20%3D%20len%28que%29%20%3D%3D%200%0A%20%20%20%20print%28%22%E9%98%9F%E5%88%97%E6%98%AF%E5%90%A6%E4%B8%BA%E7%A9%BA%20%3D%22,%20is_empty%29&cumulative=false&curInstr=3&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=311&rawInputLstJSON=%5B%5D&textReferences=false diff --git a/docs-en/chapter_stack_and_queue/stack.md b/docs-en/chapter_stack_and_queue/stack.md index e05cb87b3..4c47727b4 100755 --- a/docs-en/chapter_stack_and_queue/stack.md +++ b/docs-en/chapter_stack_and_queue/stack.md @@ -302,7 +302,7 @@ Typically, we can directly use the stack class built into the programming langua ``` -??? pythontutor "Visualizing Code" +??? pythontutor "Code Visualization" 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%E6%A0%88%0A%20%20%20%20%23%20Python%20%E6%B2%A1%E6%9C%89%E5%86%85%E7%BD%AE%E7%9A%84%E6%A0%88%E7%B1%BB%EF%BC%8C%E5%8F%AF%E4%BB%A5%E6%8A%8A%20list%20%E5%BD%93%E4%BD%9C%E6%A0%88%E6%9D%A5%E4%BD%BF%E7%94%A8%0A%20%20%20%20stack%20%3D%20%5B%5D%0A%0A%20%20%20%20%23%20%E5%85%83%E7%B4%A0%E5%85%A5%E6%A0%88%0A%20%20%20%20stack.append%281%29%0A%20%20%20%20stack.append%283%29%0A%20%20%20%20stack.append%282%29%0A%20%20%20%20stack.append%285%29%0A%20%20%20%20stack.append%284%29%0A%20%20%20%20print%28%22%E6%A0%88%20stack%20%3D%22,%20stack%29%0A%0A%20%20%20%20%23%20%E8%AE%BF%E9%97%AE%E6%A0%88%E9%A1%B6%E5%85%83%E7%B4%A0%0A%20%20%20%20peek%20%3D%20stack%5B-1%5D%0A%20%20%20%20print%28%22%E6%A0%88%E9%A1%B6%E5%85%83%E7%B4%A0%20peek%20%3D%22,%20peek%29%0A%0A%20%20%20%20%23%20%E5%85%83%E7%B4%A0%E5%87%BA%E6%A0%88%0A%20%20%20%20pop%20%3D%20stack.pop%28%29%0A%20%20%20%20print%28%22%E5%87%BA%E6%A0%88%E5%85%83%E7%B4%A0%20pop%20%3D%22,%20pop%29%0A%20%20%20%20print%28%22%E5%87%BA%E6%A0%88%E5%90%8E%20stack%20%3D%22,%20stack%29%0A%0A%20%20%20%20%23%20%E8%8E%B7%E5%8F%96%E6%A0%88%E7%9A%84%E9%95%BF%E5%BA%A6%0A%20%20%20%20size%20%3D%20len%28stack%29%0A%20%20%20%20print%28%22%E6%A0%88%E7%9A%84%E9%95%BF%E5%BA%A6%20size%20%3D%22,%20size%29%0A%0A%20%20%20%20%23%20%E5%88%A4%E6%96%AD%E6%98%AF%E5%90%A6%E4%B8%BA%E7%A9%BA%0A%20%20%20%20is_empty%20%3D%20len%28stack%29%20%3D%3D%200%0A%20%20%20%20print%28%22%E6%A0%88%E6%98%AF%E5%90%A6%E4%B8%BA%E7%A9%BA%20%3D%22,%20is_empty%29&cumulative=false&curInstr=2&heapPrimitives=nevernest&mode=display&origin=opt-frontend.js&py=311&rawInputLstJSON=%5B%5D&textReferences=false diff --git a/docs/chapter_hashing/hash_algorithm.md b/docs/chapter_hashing/hash_algorithm.md index 3c1b73f5b..8593a74ec 100644 --- a/docs/chapter_hashing/hash_algorithm.md +++ b/docs/chapter_hashing/hash_algorithm.md @@ -316,7 +316,6 @@ $$ let mut dec_hasher = DefaultHasher::new(); dec.to_bits().hash(&mut dec_hasher); let hash_dec = dec_hasher.finish(); - println!("小数 {} 的哈希值为 {}", dec, hash_dec); // 小数 3.14159 的哈希值为 2566941990314602357 let str = "Hello 算法"; diff --git a/mkdocs-en.yml b/mkdocs-en.yml index 6e0fe440a..87846ef54 100644 --- a/mkdocs-en.yml +++ b/mkdocs-en.yml @@ -67,13 +67,13 @@ nav: - 5.2 Queue: chapter_stack_and_queue/queue.md - 5.3 Double-ended Queue: chapter_stack_and_queue/deque.md - 5.4 Summary: chapter_stack_and_queue/summary.md - # - Chapter 6. Hash Table: - # # [icon: material/table-search] - # - chapter_hashing/index.md - # - 6.1 Hash Table: chapter_hashing/hash_map.md - # - 6.2 Hash Collision: chapter_hashing/hash_collision.md - # - 6.3 Hash Algorithm: chapter_hashing/hash_algorithm.md - # - 6.4 Summary: chapter_hashing/summary.md + - Chapter 6. Hash Table: + # [icon: material/table-search] + - chapter_hashing/index.md + - 6.1 Hash Table: chapter_hashing/hash_map.md + - 6.2 Hash Collision: chapter_hashing/hash_collision.md + - 6.3 Hash Algorithm: chapter_hashing/hash_algorithm.md + - 6.4 Summary: chapter_hashing/summary.md # - Chapter 7. Tree: # # [icon: material/graph-outline] # - chapter_tree/index.md