mirror of
https://github.com/krahets/hello-algo.git
synced 2026-07-16 19:11:02 +08:00
build
This commit is contained in:
@@ -15,7 +15,7 @@ There are mainly two methods for improving the structure of hash tables: "Separa
|
||||
|
||||
## 6.2.1 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. Figure 6-5 shows an example of a hash table with separate chaining.
|
||||
In the original hash table, each bucket can store only one key-value pair. <u>Separate chaining</u> transforms individual elements into a linked list, with key-value pairs as list nodes, storing all colliding key-value pairs in the same list. Figure 6-5 shows an example of a hash table with separate chaining.
|
||||
|
||||
{ class="animation-figure" }
|
||||
|
||||
@@ -1536,7 +1536,7 @@ It's worth noting that when the list is very long, the query efficiency $O(n)$ i
|
||||
|
||||
## 6.2.2 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.
|
||||
<u>Open addressing</u> 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.
|
||||
|
||||
@@ -1561,7 +1561,7 @@ It's important to note that **we cannot directly delete elements in an open addr
|
||||
|
||||
<p align="center"> Figure 6-7 Query issues caused by deletion in open addressing </p>
|
||||
|
||||
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.
|
||||
To solve this problem, we can use a <u>lazy deletion</u> 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.
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ comments: true
|
||||
|
||||
# 6.1 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.
|
||||
A <u>hash table</u> 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 Figure 6-1, 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 Figure 6-1.
|
||||
|
||||
@@ -498,9 +498,9 @@ There are three common ways to traverse a hash table: traversing key-value pairs
|
||||
|
||||
## 6.1.2 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.
|
||||
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 <u>bucket</u>, 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**.
|
||||
So, how do we locate the appropriate bucket based on the `key`? This is achieved through a <u>hash function</u>. 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:
|
||||
|
||||
@@ -1824,7 +1824,7 @@ For the hash function in the above example, if the last two digits of the input
|
||||
20336 % 100 = 36
|
||||
```
|
||||
|
||||
As shown in Figure 6-3, 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".
|
||||
As shown in Figure 6-3, 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 <u>hash collision</u>.
|
||||
|
||||
{ class="animation-figure" }
|
||||
|
||||
@@ -1840,4 +1840,4 @@ As shown in Figure 6-4, before expansion, key-value pairs `(136, A)` and `(236,
|
||||
|
||||
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.
|
||||
The <u>load factor</u> 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.
|
||||
|
||||
Reference in New Issue
Block a user