mirror of
https://github.com/krahets/hello-algo.git
synced 2025-11-02 04:31:55 +08:00
1. lower-case nouns
2. fix 2 figures 3. Replace some 「」 by “”
This commit is contained in:
@ -1,12 +1,13 @@
|
||||
# 双向队列
|
||||
|
||||
对于队列,我们仅能在头部删除或在尾部添加元素。然而,「双向队列 Deque」提供了更高的灵活性,允许在头部和尾部执行元素的添加或删除操作。
|
||||
对于队列,我们仅能在头部删除或在尾部添加元素。然而,「双向队列 deque」提供了更高的灵活性,允许在头部和尾部执行元素的添加或删除操作。
|
||||
|
||||

|
||||
|
||||
## 双向队列常用操作
|
||||
|
||||
双向队列的常用操作如下表所示,具体的方法名称需要根据所使用的编程语言来确定。
|
||||
|
||||
<p align="center"> 表:双向队列操作效率 </p>
|
||||
|
||||
| 方法名 | 描述 | 时间复杂度 |
|
||||
@ -323,7 +324,7 @@
|
||||
|
||||
回顾上一节内容,我们使用普通单向链表来实现队列,因为它可以方便地删除头节点(对应出队操作)和在尾节点后添加新节点(对应入队操作)。
|
||||
|
||||
对于双向队列而言,头部和尾部都可以执行入队和出队操作。换句话说,双向队列需要实现另一个对称方向的操作。为此,我们采用「双向链表」作为双向队列的底层数据结构。
|
||||
对于双向队列而言,头部和尾部都可以执行入队和出队操作。换句话说,双向队列需要实现另一个对称方向的操作。为此,我们采用“双向链表”作为双向队列的底层数据结构。
|
||||
|
||||
我们将双向链表的头节点和尾节点视为双向队列的队首和队尾,同时实现在两端添加和删除节点的功能。
|
||||
|
||||
|
||||
@ -1,14 +1,15 @@
|
||||
# 队列
|
||||
|
||||
「队列 Queue」是一种遵循先入先出(First In, First Out)规则的线性数据结构。顾名思义,队列模拟了排队现象,即新来的人不断加入队列的尾部,而位于队列头部的人逐个离开。
|
||||
「队列 queue」是一种遵循先入先出规则的线性数据结构。顾名思义,队列模拟了排队现象,即新来的人不断加入队列的尾部,而位于队列头部的人逐个离开。
|
||||
|
||||
我们把队列的头部称为「队首」,尾部称为「队尾」,把将元素加入队尾的操作称为「入队」,删除队首元素的操作称为「出队」。
|
||||
我们把队列的头部称为“队首”,尾部称为“队尾”,把将元素加入队尾的操作称为“入队”,删除队首元素的操作称为“出队”。
|
||||
|
||||

|
||||
|
||||
## 队列常用操作
|
||||
|
||||
队列的常见操作如下表所示。需要注意的是,不同编程语言的方法名称可能会有所不同。我们在此采用与栈相同的方法命名。
|
||||
|
||||
<p align="center"> 表:队列操作效率 </p>
|
||||
|
||||
| 方法名 | 描述 | 时间复杂度 |
|
||||
@ -288,7 +289,7 @@
|
||||
|
||||
### 基于链表的实现
|
||||
|
||||
对于链表实现,我们可以将链表的「头节点」和「尾节点」分别视为队首和队尾,规定队尾仅可添加节点,而队首仅可删除节点。
|
||||
对于链表实现,我们可以将链表的“头节点”和“尾节点”分别视为“队首”和“队尾”,规定队尾仅可添加节点,队首仅可删除节点。
|
||||
|
||||
=== "LinkedListQueue"
|
||||

|
||||
@ -395,7 +396,7 @@
|
||||
=== "pop()"
|
||||

|
||||
|
||||
你可能会发现一个问题:在不断进行入队和出队的过程中,`front` 和 `rear` 都在向右移动,**当它们到达数组尾部时就无法继续移动了**。为解决此问题,我们可以将数组视为首尾相接的「环形数组」。
|
||||
你可能会发现一个问题:在不断进行入队和出队的过程中,`front` 和 `rear` 都在向右移动,**当它们到达数组尾部时就无法继续移动了**。为解决此问题,我们可以将数组视为首尾相接的“环形数组”。
|
||||
|
||||
对于环形数组,我们需要让 `front` 或 `rear` 在越过数组尾部时,直接回到数组头部继续遍历。这种周期性规律可以通过“取余操作”来实现,代码如下所示。
|
||||
|
||||
|
||||
@ -1,16 +1,17 @@
|
||||
# 栈
|
||||
|
||||
「栈 Stack」是一种遵循先入后出(First In, Last Out)原则的线性数据结构。
|
||||
「栈 stack」是一种遵循先入后出的逻辑的线性数据结构。
|
||||
|
||||
我们可以将栈类比为桌面上的一摞盘子,如果需要拿出底部的盘子,则需要先将上面的盘子依次取出。我们将盘子替换为各种类型的元素(如整数、字符、对象等),就得到了栈数据结构。
|
||||
|
||||
在栈中,我们把堆叠元素的顶部称为「栈顶」,底部称为「栈底」。将把元素添加到栈顶的操作叫做「入栈」,而删除栈顶元素的操作叫做「出栈」。
|
||||
在栈中,我们把堆叠元素的顶部称为“栈顶”,底部称为“栈底”。将把元素添加到栈顶的操作叫做“入栈”,而删除栈顶元素的操作叫做“出栈”。
|
||||
|
||||

|
||||
|
||||
## 栈常用操作
|
||||
|
||||
栈的常用操作如下表所示,具体的方法名需要根据所使用的编程语言来确定。在此,我们以常见的 `push()` , `pop()` , `peek()` 命名为例。
|
||||
|
||||
<p align="center"> 表:栈的操作效率 </p>
|
||||
|
||||
| 方法 | 描述 | 时间复杂度 |
|
||||
@ -19,7 +20,7 @@
|
||||
| pop() | 栈顶元素出栈 | $O(1)$ |
|
||||
| peek() | 访问栈顶元素 | $O(1)$ |
|
||||
|
||||
通常情况下,我们可以直接使用编程语言内置的栈类。然而,某些语言可能没有专门提供栈类,这时我们可以将该语言的「数组」或「链表」视作栈来使用,并通过“脑补”来忽略与栈无关的操作。
|
||||
通常情况下,我们可以直接使用编程语言内置的栈类。然而,某些语言可能没有专门提供栈类,这时我们可以将该语言的“数组”或“链表”视作栈来使用,并在程序逻辑上忽略与栈无关的操作。
|
||||
|
||||
=== "Java"
|
||||
|
||||
@ -377,7 +378,7 @@
|
||||
|
||||
### 基于数组的实现
|
||||
|
||||
在基于「数组」实现栈时,我们可以将数组的尾部作为栈顶。在这样的设计下,入栈与出栈操作就分别对应在数组尾部添加元素与删除元素,时间复杂度都为 $O(1)$ 。
|
||||
使用数组实现栈时,我们可以将数组的尾部作为栈顶。在这样的设计下,入栈与出栈操作就分别对应在数组尾部添加元素与删除元素,时间复杂度都为 $O(1)$ 。
|
||||
|
||||
=== "ArrayStack"
|
||||

|
||||
@ -489,5 +490,5 @@
|
||||
|
||||
## 栈典型应用
|
||||
|
||||
- **浏览器中的后退与前进、软件中的撤销与反撤销**。每当我们打开新的网页,浏览器就会将上一个网页执行入栈,这样我们就可以通过「后退」操作回到上一页面。后退操作实际上是在执行出栈。如果要同时支持后退和前进,那么需要两个栈来配合实现。
|
||||
- **浏览器中的后退与前进、软件中的撤销与反撤销**。每当我们打开新的网页,浏览器就会将上一个网页执行入栈,这样我们就可以通过后退操作回到上一页面。后退操作实际上是在执行出栈。如果要同时支持后退和前进,那么需要两个栈来配合实现。
|
||||
- **程序内存管理**。每次调用函数时,系统都会在栈顶添加一个栈帧,用于记录函数的上下文信息。在递归函数中,向下递推阶段会不断执行入栈操作,而向上回溯阶段则会执行出栈操作。
|
||||
|
||||
Reference in New Issue
Block a user