mirror of
https://github.com/krahets/hello-algo.git
synced 2026-02-03 10:53:35 +08:00
feat: Revised the book (#978)
* Sync recent changes to the revised Word. * Revised the preface chapter * Revised the introduction chapter * Revised the computation complexity chapter * Revised the chapter data structure * Revised the chapter array and linked list * Revised the chapter stack and queue * Revised the chapter hashing * Revised the chapter tree * Revised the chapter heap * Revised the chapter graph * Revised the chapter searching * Reivised the sorting chapter * Revised the divide and conquer chapter * Revised the chapter backtacking * Revised the DP chapter * Revised the greedy chapter * Revised the appendix chapter * Revised the preface chapter doubly * Revised the figures
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
# 队列
|
||||
|
||||
「队列 queue」是一种遵循先入先出规则的线性数据结构。顾名思义,队列模拟了排队现象,即新来的人不断加入队列的尾部,而位于队列头部的人逐个离开。
|
||||
「队列 queue」是一种遵循先入先出规则的线性数据结构。顾名思义,队列模拟了排队现象,即新来的人不断加入队列尾部,而位于队列头部的人逐个离开。
|
||||
|
||||
如下图所示,我们将队列的头部称为“队首”,尾部称为“队尾”,将把元素加入队尾的操作称为“入队”,删除队首元素的操作称为“出队”。
|
||||
如下图所示,我们将队列头部称为“队首”,尾部称为“队尾”,将把元素加入队尾的操作称为“入队”,删除队首元素的操作称为“出队”。
|
||||
|
||||

|
||||
|
||||
@@ -18,15 +18,17 @@
|
||||
| pop() | 队首元素出队 | $O(1)$ |
|
||||
| peek() | 访问队首元素 | $O(1)$ |
|
||||
|
||||
我们可以直接使用编程语言中现成的队列类。
|
||||
我们可以直接使用编程语言中现成的队列类:
|
||||
|
||||
=== "Python"
|
||||
|
||||
```python title="queue.py"
|
||||
from collections import deque
|
||||
|
||||
# 初始化队列
|
||||
# 在 Python 中,我们一般将双向队列类 deque 看作队列使用
|
||||
# 虽然 queue.Queue() 是纯正的队列类,但不太好用,因此不建议
|
||||
que: deque[int] = collections.deque()
|
||||
# 在 Python 中,我们一般将双向队列类 deque 当作队列使用
|
||||
# 虽然 queue.Queue() 是纯正的队列类,但不太好用,因此不推荐
|
||||
que: deque[int] = deque()
|
||||
|
||||
# 元素入队
|
||||
que.append(1)
|
||||
@@ -308,7 +310,7 @@
|
||||
|
||||
## 队列实现
|
||||
|
||||
为了实现队列,我们需要一种数据结构,可以在一端添加元素,并在另一端删除元素。因此,链表和数组都可以用来实现队列。
|
||||
为了实现队列,我们需要一种数据结构,可以在一端添加元素,并在另一端删除元素。链表和数组都符合要求。
|
||||
|
||||
### 基于链表的实现
|
||||
|
||||
@@ -323,7 +325,7 @@
|
||||
=== "pop()"
|
||||

|
||||
|
||||
以下是用链表实现队列的代码。
|
||||
以下是用链表实现队列的代码:
|
||||
|
||||
```src
|
||||
[file]{linkedlist_queue}-[class]{linked_list_queue}-[func]{}
|
||||
@@ -331,7 +333,7 @@
|
||||
|
||||
### 基于数组的实现
|
||||
|
||||
由于数组删除首元素的时间复杂度为 $O(n)$ ,这会导致出队操作效率较低。然而,我们可以采用以下巧妙方法来避免这个问题。
|
||||
在数组中删除首元素的时间复杂度为 $O(n)$ ,这会导致出队操作效率较低。然而,我们可以采用以下巧妙方法来避免这个问题。
|
||||
|
||||
我们可以使用一个变量 `front` 指向队首元素的索引,并维护一个变量 `size` 用于记录队列长度。定义 `rear = front + size` ,这个公式计算出的 `rear` 指向队尾元素之后的下一个位置。
|
||||
|
||||
@@ -351,19 +353,19 @@
|
||||
=== "pop()"
|
||||

|
||||
|
||||
你可能会发现一个问题:在不断进行入队和出队的过程中,`front` 和 `rear` 都在向右移动,**当它们到达数组尾部时就无法继续移动了**。为解决此问题,我们可以将数组视为首尾相接的“环形数组”。
|
||||
你可能会发现一个问题:在不断进行入队和出队的过程中,`front` 和 `rear` 都在向右移动,**当它们到达数组尾部时就无法继续移动了**。为了解决此问题,我们可以将数组视为首尾相接的“环形数组”。
|
||||
|
||||
对于环形数组,我们需要让 `front` 或 `rear` 在越过数组尾部时,直接回到数组头部继续遍历。这种周期性规律可以通过“取余操作”来实现,代码如下所示。
|
||||
对于环形数组,我们需要让 `front` 或 `rear` 在越过数组尾部时,直接回到数组头部继续遍历。这种周期性规律可以通过“取余操作”来实现,代码如下所示:
|
||||
|
||||
```src
|
||||
[file]{array_queue}-[class]{array_queue}-[func]{}
|
||||
```
|
||||
|
||||
以上实现的队列仍然具有局限性,即其长度不可变。然而,这个问题不难解决,我们可以将数组替换为动态数组,从而引入扩容机制。有兴趣的同学可以尝试自行实现。
|
||||
以上实现的队列仍然具有局限性:其长度不可变。然而,这个问题不难解决,我们可以将数组替换为动态数组,从而引入扩容机制。有兴趣的读者可以尝试自行实现。
|
||||
|
||||
两种实现的对比结论与栈一致,在此不再赘述。
|
||||
|
||||
## 队列典型应用
|
||||
|
||||
- **淘宝订单**。购物者下单后,订单将加入队列中,系统随后会根据顺序依次处理队列中的订单。在双十一期间,短时间内会产生海量订单,高并发成为工程师们需要重点攻克的问题。
|
||||
- **各类待办事项**。任何需要实现“先来后到”功能的场景,例如打印机的任务队列、餐厅的出餐队列等。队列在这些场景中可以有效地维护处理顺序。
|
||||
- **淘宝订单**。购物者下单后,订单将加入队列中,系统随后会根据顺序处理队列中的订单。在双十一期间,短时间内会产生海量订单,高并发成为工程师们需要重点攻克的问题。
|
||||
- **各类待办事项**。任何需要实现“先来后到”功能的场景,例如打印机的任务队列、餐厅的出餐队列等,队列在这些场景中可以有效地维护处理顺序。
|
||||
|
||||
Reference in New Issue
Block a user