Revisit the English version (#1835)

* Review the English version using Claude-4.5.

* Update mkdocs.yml

* Align the section titles.

* Bug fixes
This commit is contained in:
Yudong Jin
2025-12-30 17:54:01 +08:00
committed by GitHub
parent 091afd38b4
commit 45e1295241
106 changed files with 4195 additions and 3398 deletions

View File

@@ -1,22 +1,22 @@
# Queue
A <u>queue</u> is a linear data structure that follows the First-In-First-Out (FIFO) rule. As the name suggests, a queue simulates the phenomenon of lining up, where newcomers join the queue at the rear, and the person at the front leaves the queue first.
A <u>queue</u> is a linear data structure that follows the First In First Out (FIFO) rule. As the name suggests, a queue simulates the phenomenon of lining up, where newcomers continuously join the end of the queue, while people at the front of the queue leave one by one.
As shown in the figure below, we call the front of the queue the "head" and the back the "tail." The operation of adding elements to the rear of the queue is termed "enqueue," and the operation of removing elements from the front is termed "dequeue."
As shown in the figure below, we call the front of the queue the "front" and the end the "rear." The operation of adding an element to the rear is called "enqueue," and the operation of removing the front element is called "dequeue."
![Queue's first-in-first-out rule](queue.assets/queue_operations.png)
![FIFO rule of queue](queue.assets/queue_operations.png)
## Common operations on queue
## Common Queue Operations
The common operations on a queue are shown in the table below. Note that method names may vary across different programming languages. Here, we use the same naming convention as that used for stacks.
The common operations on a queue are shown in the table below. Note that method names may vary across different programming languages. We adopt the same naming convention as for stacks here.
<p align="center"> Table <id> &nbsp; Efficiency of queue operations </p>
<p align="center"> Table <id> &nbsp; Efficiency of Queue Operations </p>
| Method Name | Description | Time Complexity |
| ----------- | -------------------------------------- | --------------- |
| `push()` | Enqueue an element, add it to the tail | $O(1)$ |
| `pop()` | Dequeue the head element | $O(1)$ |
| `peek()` | Access the head element | $O(1)$ |
| Method | Description | Time Complexity |
| -------- | ------------------------------------------ | --------------- |
| `push()` | Enqueue element, add element to rear | $O(1)$ |
| `pop()` | Dequeue front element | $O(1)$ |
| `peek()` | Access front element | $O(1)$ |
We can directly use the ready-made queue classes in programming languages:
@@ -25,9 +25,9 @@ We can directly use the ready-made queue classes in programming languages:
```python title="queue.py"
from collections import deque
# Initialize the queue
# Initialize queue
# In Python, we generally use the deque class as a queue
# Although queue.Queue() is a pure queue class, it's not very user-friendly, so it's not recommended
# Although queue.Queue() is a pure queue class, it is not very user-friendly, so it is not recommended
que: deque[int] = deque()
# Enqueue elements
@@ -37,23 +37,23 @@ We can directly use the ready-made queue classes in programming languages:
que.append(5)
que.append(4)
# Access the first element
# Access front element
front: int = que[0]
# Dequeue an element
# Dequeue element
pop: int = que.popleft()
# Get the length of the queue
# Get queue length
size: int = len(que)
# Check if the queue is empty
# Check if queue is empty
is_empty: bool = len(que) == 0
```
=== "C++"
```cpp title="queue.cpp"
/* Initialize the queue */
/* Initialize queue */
queue<int> queue;
/* Enqueue elements */
@@ -63,23 +63,23 @@ We can directly use the ready-made queue classes in programming languages:
queue.push(5);
queue.push(4);
/* Access the first element*/
/* Access front element */
int front = queue.front();
/* Dequeue an element */
/* Dequeue element */
queue.pop();
/* Get the length of the queue */
/* Get queue length */
int size = queue.size();
/* Check if the queue is empty */
/* Check if queue is empty */
bool empty = queue.empty();
```
=== "Java"
```java title="queue.java"
/* Initialize the queue */
/* Initialize queue */
Queue<Integer> queue = new LinkedList<>();
/* Enqueue elements */
@@ -89,23 +89,23 @@ We can directly use the ready-made queue classes in programming languages:
queue.offer(5);
queue.offer(4);
/* Access the first element */
/* Access front element */
int peek = queue.peek();
/* Dequeue an element */
/* Dequeue element */
int pop = queue.poll();
/* Get the length of the queue */
/* Get queue length */
int size = queue.size();
/* Check if the queue is empty */
/* Check if queue is empty */
boolean isEmpty = queue.isEmpty();
```
=== "C#"
```csharp title="queue.cs"
/* Initialize the queue */
/* Initialize queue */
Queue<int> queue = new();
/* Enqueue elements */
@@ -115,23 +115,23 @@ We can directly use the ready-made queue classes in programming languages:
queue.Enqueue(5);
queue.Enqueue(4);
/* Access the first element */
/* Access front element */
int peek = queue.Peek();
/* Dequeue an element */
/* Dequeue element */
int pop = queue.Dequeue();
/* Get the length of the queue */
/* Get queue length */
int size = queue.Count;
/* Check if the queue is empty */
/* Check if queue is empty */
bool isEmpty = queue.Count == 0;
```
=== "Go"
```go title="queue_test.go"
/* Initialize the queue */
/* Initialize queue */
// In Go, use list as a queue
queue := list.New()
@@ -142,25 +142,25 @@ We can directly use the ready-made queue classes in programming languages:
queue.PushBack(5)
queue.PushBack(4)
/* Access the first element */
/* Access front element */
peek := queue.Front()
/* Dequeue an element */
/* Dequeue element */
pop := queue.Front()
queue.Remove(pop)
/* Get the length of the queue */
/* Get queue length */
size := queue.Len()
/* Check if the queue is empty */
/* Check if queue is empty */
isEmpty := queue.Len() == 0
```
=== "Swift"
```swift title="queue.swift"
/* Initialize the queue */
// Swift does not have a built-in queue class, so Array can be used as a queue
/* Initialize queue */
// Swift does not have a built-in queue class, can use Array as a queue
var queue: [Int] = []
/* Enqueue elements */
@@ -170,25 +170,25 @@ We can directly use the ready-made queue classes in programming languages:
queue.append(5)
queue.append(4)
/* Access the first element */
/* Access front element */
let peek = queue.first!
/* Dequeue an element */
// Since it's an array, removeFirst has a complexity of O(n)
/* Dequeue element */
// Since it's an array, removeFirst has O(n) complexity
let pool = queue.removeFirst()
/* Get the length of the queue */
/* Get queue length */
let size = queue.count
/* Check if the queue is empty */
/* Check if queue is empty */
let isEmpty = queue.isEmpty
```
=== "JS"
```javascript title="queue.js"
/* Initialize the queue */
// JavaScript does not have a built-in queue, so Array can be used as a queue
/* Initialize queue */
// JavaScript does not have a built-in queue, can use Array as a queue
const queue = [];
/* Enqueue elements */
@@ -198,25 +198,25 @@ We can directly use the ready-made queue classes in programming languages:
queue.push(5);
queue.push(4);
/* Access the first element */
/* Access front element */
const peek = queue[0];
/* Dequeue an element */
// Since the underlying structure is an array, shift() method has a time complexity of O(n)
/* Dequeue element */
// The underlying structure is an array, so shift() has O(n) time complexity
const pop = queue.shift();
/* Get the length of the queue */
/* Get queue length */
const size = queue.length;
/* Check if the queue is empty */
/* Check if queue is empty */
const empty = queue.length === 0;
```
=== "TS"
```typescript title="queue.ts"
/* Initialize the queue */
// TypeScript does not have a built-in queue, so Array can be used as a queue
/* Initialize queue */
// TypeScript does not have a built-in queue, can use Array as a queue
const queue: number[] = [];
/* Enqueue elements */
@@ -226,25 +226,25 @@ We can directly use the ready-made queue classes in programming languages:
queue.push(5);
queue.push(4);
/* Access the first element */
/* Access front element */
const peek = queue[0];
/* Dequeue an element */
// Since the underlying structure is an array, shift() method has a time complexity of O(n)
/* Dequeue element */
// The underlying structure is an array, so shift() has O(n) time complexity
const pop = queue.shift();
/* Get the length of the queue */
/* Get queue length */
const size = queue.length;
/* Check if the queue is empty */
/* Check if queue is empty */
const empty = queue.length === 0;
```
=== "Dart"
```dart title="queue.dart"
/* Initialize the queue */
// In Dart, the Queue class is a double-ended queue but can be used as a queue
/* Initialize queue */
// In Dart, the Queue class is a deque and can also be used as a queue
Queue<int> queue = Queue();
/* Enqueue elements */
@@ -254,24 +254,24 @@ We can directly use the ready-made queue classes in programming languages:
queue.add(5);
queue.add(4);
/* Access the first element */
/* Access front element */
int peek = queue.first;
/* Dequeue an element */
/* Dequeue element */
int pop = queue.removeFirst();
/* Get the length of the queue */
/* Get queue length */
int size = queue.length;
/* Check if the queue is empty */
/* Check if queue is empty */
bool isEmpty = queue.isEmpty;
```
=== "Rust"
```rust title="queue.rs"
/* Initialize the double-ended queue */
// In Rust, use a double-ended queue as a regular queue
/* Initialize deque */
// In Rust, use deque as a regular queue
let mut deque: VecDeque<u32> = VecDeque::new();
/* Enqueue elements */
@@ -281,18 +281,18 @@ We can directly use the ready-made queue classes in programming languages:
deque.push_back(5);
deque.push_back(4);
/* Access the first element */
/* Access front element */
if let Some(front) = deque.front() {
}
/* Dequeue an element */
/* Dequeue element */
if let Some(pop) = deque.pop_front() {
}
/* Get the length of the queue */
/* Get queue length */
let size = deque.len();
/* Check if the queue is empty */
/* Check if queue is empty */
let is_empty = deque.is_empty();
```
@@ -305,7 +305,55 @@ We can directly use the ready-made queue classes in programming languages:
=== "Kotlin"
```kotlin title="queue.kt"
/* Initialize queue */
val queue = LinkedList<Int>()
/* Enqueue elements */
queue.offer(1)
queue.offer(3)
queue.offer(2)
queue.offer(5)
queue.offer(4)
/* Access front element */
val peek = queue.peek()
/* Dequeue element */
val pop = queue.poll()
/* Get queue length */
val size = queue.size
/* Check if queue is empty */
val isEmpty = queue.isEmpty()
```
=== "Ruby"
```ruby title="queue.rb"
# Initialize queue
# Ruby's built-in queue (Thread::Queue) does not have peek and traversal methods, can use Array as a queue
queue = []
# Enqueue elements
queue.push(1)
queue.push(3)
queue.push(2)
queue.push(5)
queue.push(4)
# Access front element
peek = queue.first
# Dequeue element
# Please note that since it's an array, Array#shift has O(n) time complexity
pop = queue.shift
# Get queue length
size = queue.length
# Check if queue is empty
is_empty = queue.empty?
```
=== "Zig"
@@ -314,20 +362,20 @@ We can directly use the ready-made queue classes in programming languages:
```
??? pythontutor "Code Visualization"
??? pythontutor "Visualize Execution"
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
## Implementing a queue
## Queue Implementation
To implement a queue, we need a data structure that allows adding elements at one end and removing them at the other. Both linked lists and arrays meet this requirement.
To implement a queue, we need a data structure that allows adding elements at one end and removing elements at the other end. Both linked lists and arrays meet this requirement.
### Implementation based on a linked list
### Linked List Implementation
As shown in the figure below, we can consider the "head node" and "tail node" of a linked list as the "front" and "rear" of the queue, respectively. It is stipulated that nodes can only be added at the rear and removed at the front.
As shown in the figure below, we can treat the "head node" and "tail node" of a linked list as the "front" and "rear" of the queue, respectively, with the rule that nodes can only be added at the rear and removed from the front.
=== "LinkedListQueue"
![Implementing Queue with Linked List for Enqueue and Dequeue Operations](queue.assets/linkedlist_queue_step1.png)
![Enqueue and dequeue operations in linked list implementation of queue](queue.assets/linkedlist_queue_step1.png)
=== "push()"
![linkedlist_queue_push](queue.assets/linkedlist_queue_step2_push.png)
@@ -341,21 +389,21 @@ Below is the code for implementing a queue using a linked list:
[file]{linkedlist_queue}-[class]{linked_list_queue}-[func]{}
```
### Implementation based on an array
### Array Implementation
Deleting the first element in an array has a time complexity of $O(n)$, which would make the dequeue operation inefficient. However, this problem can be cleverly avoided as follows.
Deleting the first element in an array has a time complexity of $O(n)$, which would make the dequeue operation inefficient. However, we can use the following clever method to avoid this problem.
We use a variable `front` to indicate the index of the front element and maintain a variable `size` to record the queue's length. Define `rear = front + size`, which points to the position immediately following the tail element.
We can use a variable `front` to point to the index of the front element and maintain a variable `size` to record the queue length. We define `rear = front + size`, which calculates the position right after the rear element.
With this design, **the effective interval of elements in the array is `[front, rear - 1]`**. The implementation methods for various operations are shown in the figure below.
Based on this design, **the valid interval containing elements in the array is `[front, rear - 1]`**. The implementation methods for various operations are shown in the figure below:
- Enqueue operation: Assign the input element to the `rear` index and increase `size` by 1.
- Dequeue operation: Simply increase `front` by 1 and decrease `size` by 1.
Both enqueue and dequeue operations only require a single operation, each with a time complexity of $O(1)$.
As you can see, both enqueue and dequeue operations require only one operation, with a time complexity of $O(1)$.
=== "ArrayQueue"
![Implementing Queue with Array for Enqueue and Dequeue Operations](queue.assets/array_queue_step1.png)
![Enqueue and dequeue operations in array implementation of queue](queue.assets/array_queue_step1.png)
=== "push()"
![array_queue_push](queue.assets/array_queue_step2_push.png)
@@ -363,19 +411,19 @@ Both enqueue and dequeue operations only require a single operation, each with a
=== "pop()"
![array_queue_pop](queue.assets/array_queue_step3_pop.png)
You might notice a problem: as enqueue and dequeue operations are continuously performed, both `front` and `rear` move to the right and **will eventually reach the end of the array and can't move further**. To resolve this, we can treat the array as a "circular array" where connecting the end of the array back to its beginning.
You may notice a problem: as we continuously enqueue and dequeue, both `front` and `rear` move to the right. **When they reach the end of the array, they cannot continue moving**. To solve this problem, we can treat the array as a "circular array" with head and tail connected.
In a circular array, `front` or `rear` needs to loop back to the start of the array upon reaching the end. This cyclical pattern can be achieved with a "modulo operation" as shown in the code below:
For a circular array, we need to let `front` or `rear` wrap around to the beginning of the array when they cross the end. This periodic pattern can be implemented using the "modulo operation," as shown in the code below:
```src
[file]{array_queue}-[class]{array_queue}-[func]{}
```
The above implementation of the queue still has its limitations: its length is fixed. However, this issue is not difficult to resolve. We can replace the array with a dynamic array that can expand itself if needed. Interested readers can try to implement this themselves.
The queue implemented above still has limitations: its length is immutable. However, this problem is not difficult to solve. We can replace the array with a dynamic array to introduce an expansion mechanism. Interested readers can try to implement this themselves.
The comparison of the two implementations is consistent with that of the stack and is not repeated here.
The comparison conclusions for the two implementations are consistent with those for stacks and will not be repeated here.
## Typical applications of queue
## Typical Applications of Queue
- **Amazon orders**: After shoppers place orders, these orders join a queue, and the system processes them in order. During events like Singles' Day, a massive number of orders are generated in a short time, making high concurrency a key challenge for engineers.
- **Various to-do lists**: Any scenario requiring a "first-come, first-served" functionality, such as a printer's task queue or a restaurant's food delivery queue, can effectively maintain the order of processing with a queue.
- **Taobao orders**. After shoppers place orders, the orders are added to a queue, and the system subsequently processes the orders in the queue according to their sequence. During Double Eleven, massive orders are generated in a short time, and high concurrency becomes a key challenge that engineers need to tackle.
- **Various to-do tasks**. Any scenario that needs to implement "first come, first served" functionality, such as a printer's task queue or a restaurant's order queue, can effectively maintain the processing order using queues.