|
1 |
| -## 1. 堆栈简介 |
| 1 | +## 1. 栈简介 |
2 | 2 |
|
3 |
| -> **堆栈(Stack)**:简称为栈。一种线性表数据结构,是一种只允许在表的一端进行插入和删除操作的线性表。 |
| 3 | +> **栈(Stack)**:也叫做「堆栈」,是一种线性表数据结构,是一种只允许在表的一端进行插入和删除操作的线性表。 |
4 | 4 |
|
5 | 5 | 我们把栈中允许插入和删除的一端称为 **「栈顶(top)」**;另一端则称为 **「栈底(bottom)」**。当表中没有任何数据元素时,称之为 **「空栈」**。
|
6 | 6 |
|
7 |
| -堆栈有两种基本操作:**「插入操作」** 和 **「删除操作」**。 |
| 7 | +栈有两种基本操作:**「插入操作」** 和 **「删除操作」**。 |
8 | 8 |
|
9 | 9 | - 栈的插入操作又称为「入栈」或者「进栈」。
|
10 | 10 | - 栈的删除操作又称为「出栈」或者「退栈」。
|
11 | 11 |
|
12 |
| - |
| 12 | + |
13 | 13 |
|
14 | 14 | 简单来说,栈是一种 **「后进先出(Last In First Out)」** 的线性表,简称为 **「LIFO 结构」**。
|
15 | 15 |
|
|
21 | 21 |
|
22 | 22 | - 第二个方面是 **「后进先出原则」**。
|
23 | 23 |
|
24 |
| -根据堆栈的定义,每次删除的总是堆栈中当前的栈顶元素,即最后进入堆栈的元素。而在进栈时,最先进入堆栈的元素一定在栈底,最后进入堆栈的元素一定在栈顶。也就是说,元素进入堆栈或者退出退栈是按照「后进先出(Last In First Out)」的原则进行的。 |
| 24 | +根据栈的定义,每次删除的总是栈中当前的栈顶元素,即最后进入栈的元素。而在进栈时,最先进入栈的元素一定在栈底,最后进入栈的元素一定在栈顶。也就是说,元素进入栈或者退出退栈是按照「后进先出(Last In First Out)」的原则进行的。 |
25 | 25 |
|
26 |
| -## 2. 堆栈的顺序存储与链式存储 |
| 26 | +## 2. 栈的顺序存储与链式存储 |
27 | 27 |
|
28 | 28 | 和线性表类似,栈有两种存储表示方法:**「顺序栈」** 和 **「链式栈」**。
|
29 | 29 |
|
30 |
| -- **「顺序栈」**:即堆栈的顺序存储结构。利用一组地址连续的存储单元依次存放自栈底到栈顶的元素,同时使用指针 $top$ 指示栈顶元素在顺序栈中的位置。 |
31 |
| -- **「链式栈」**:即堆栈的链式存储结构。利用单链表的方式来实现堆栈。栈中元素按照插入顺序依次插入到链表的第一个节点之前,并使用栈顶指针 $top$ 指示栈顶元素,$top$ 永远指向链表的头节点位置。 |
| 30 | +- **「顺序栈」**:即栈的顺序存储结构。利用一组地址连续的存储单元依次存放自栈底到栈顶的元素,同时使用指针 $top$ 指示栈顶元素在顺序栈中的位置。 |
| 31 | +- **「链式栈」**:即栈的链式存储结构。利用单链表的方式来实现栈。栈中元素按照插入顺序依次插入到链表的第一个节点之前,并使用栈顶指针 $top$ 指示栈顶元素,$top$ 永远指向链表的头节点位置。 |
32 | 32 |
|
33 |
| -在描述堆栈的顺序存储与链式存储具体实现之前,我们先来看看堆栈具有哪些基本操作。 |
| 33 | +在描述栈的顺序存储与链式存储具体实现之前,我们先来看看栈具有哪些基本操作。 |
34 | 34 |
|
35 |
| -### 2.1 堆栈的基本操作 |
| 35 | +### 2.1 栈的基本操作 |
36 | 36 |
|
37 | 37 | 栈作为一种线性表来说,理论上应该具备线性表所有的操作特性,但由于「后进先出」的特殊性,所以针对栈的操作进行了一些变化。尤其是插入操作和删除操作,改为了入栈(push)和出栈(pop)。
|
38 | 38 |
|
39 |
| -堆栈的基本操作如下: |
| 39 | +栈的基本操作如下: |
40 | 40 |
|
41 | 41 | - **初始化空栈**:创建一个空栈,定义栈的大小 $size$,以及栈顶元素指针 $top$。
|
42 | 42 |
|
43 |
| -- **判断栈是否为空**:当堆栈为空时,返回 $True$。当堆栈不为空时,返回 $False$。一般只用于栈中删除操作和获取当前栈顶元素操作中。 |
| 43 | +- **判断栈是否为空**:当栈为空时,返回 $True$。当栈不为空时,返回 $False$。一般只用于栈中删除操作和获取当前栈顶元素操作中。 |
44 | 44 |
|
45 |
| -- **判断栈是否已满**:当堆栈已满时,返回 $True$,当堆栈未满时,返回 $False$。一般只用于顺序栈中插入元素和获取当前栈顶元素操作中。 |
| 45 | +- **判断栈是否已满**:当栈已满时,返回 $True$,当栈未满时,返回 $False$。一般只用于顺序栈中插入元素和获取当前栈顶元素操作中。 |
46 | 46 |
|
47 | 47 | - **插入元素(进栈、入栈)**:相当于在线性表最后元素后面插入一个新的数据元素。并改变栈顶指针 $top$ 的指向位置。
|
48 | 48 |
|
|
51 | 51 |
|
52 | 52 | 接下来我们来看一下栈的顺序存储与链式存储两种不同的实现方式。
|
53 | 53 |
|
54 |
| -### 2.2 堆栈的顺序存储实现 |
| 54 | +### 2.2 栈的顺序存储实现 |
55 | 55 |
|
56 |
| -堆栈最简单的实现方式就是借助于一个数组来描述堆栈的顺序存储结构。在 Python 中我们可以借助列表 $list$ 来实现。这种采用顺序存储结构的堆栈也被称为 **「顺序栈」**。 |
| 56 | +栈最简单的实现方式就是借助于一个数组来描述栈的顺序存储结构。在 Python 中我们可以借助列表 $list$ 来实现。这种采用顺序存储结构的栈也被称为 **「顺序栈」**。 |
57 | 57 |
|
58 |
| -#### 2.2.1 堆栈的顺序存储基本描述 |
| 58 | +#### 2.2.1 栈的顺序存储基本描述 |
59 | 59 |
|
60 |
| - |
| 60 | + |
61 | 61 |
|
62 | 62 | 我们约定 $self.top$ 指向栈顶元素所在位置。
|
63 | 63 |
|
64 | 64 | - **初始化空栈**:使用列表创建一个空栈,定义栈的大小 $self.size$,并令栈顶元素指针 $self.top$ 指向 $-1$,即 $self.top = -1$。
|
65 |
| -- **判断栈是否为空**:当 $self.top == -1$ 时,说明堆栈为空,返回 $True$,否则返回 $False$。 |
66 |
| -- **判断栈是否已满**:当 $self.top == self.size - 1$,说明堆栈已满,返回 $True$,否则返回返回 $False$。 |
67 |
| -- **插入元素(进栈、入栈)**:先判断堆栈是否已满,已满直接抛出异常。如果堆栈未满,则在 $self.stack$ 末尾插入新的数据元素,并令 $self.top$ 向右移动 $1$ 位。 |
68 |
| -- **删除元素(出栈、退栈)**:先判断堆栈是否为空,为空直接抛出异常。如果堆栈不为空,则删除 $self.stack$ 末尾的数据元素,并令 $self.top$ 向左移动 $1$ 位。 |
69 |
| -- **获取栈顶元素**:先判断堆栈是否为空,为空直接抛出异常。不为空则返回 $self.top$ 指向的栈顶元素,即 $self.stack[self.top]$。 |
| 65 | +- **判断栈是否为空**:当 $self.top == -1$ 时,说明栈为空,返回 $True$,否则返回 $False$。 |
| 66 | +- **判断栈是否已满**:当 $self.top == self.size - 1$,说明栈已满,返回 $True$,否则返回返回 $False$。 |
| 67 | +- **插入元素(进栈、入栈)**:先判断栈是否已满,已满直接抛出异常。如果栈未满,则在 $self.stack$ 末尾插入新的数据元素,并令 $self.top$ 向右移动 $1$ 位。 |
| 68 | +- **删除元素(出栈、退栈)**:先判断栈是否为空,为空直接抛出异常。如果栈不为空,则删除 $self.stack$ 末尾的数据元素,并令 $self.top$ 向左移动 $1$ 位。 |
| 69 | +- **获取栈顶元素**:先判断栈是否为空,为空直接抛出异常。不为空则返回 $self.top$ 指向的栈顶元素,即 $self.stack[self.top]$。 |
70 | 70 |
|
71 |
| -#### 2.2.2 堆栈的顺序存储实现代码 |
| 71 | +#### 2.2.2 栈的顺序存储实现代码 |
72 | 72 |
|
73 | 73 | ```python
|
74 | 74 | class Stack:
|
@@ -110,23 +110,23 @@ class Stack:
|
110 | 110 | return self.stack[self.top]
|
111 | 111 | ```
|
112 | 112 |
|
113 |
| -### 2.3 堆栈的链式存储实现 |
| 113 | +### 2.3 栈的链式存储实现 |
114 | 114 |
|
115 |
| -堆栈的顺序存储结构保留着顺序存储分配空间的固有缺陷,即在栈满或者其他需要重新调整存储空间时需要移动大量元素。为此,堆栈可以采用链式存储方式来实现。在 Python 中我们通过构造链表节点 $Node$ 的方式来实现。这种采用链式存储结构的堆栈也被称为 **「链式栈」**。 |
| 115 | +栈的顺序存储结构保留着顺序存储分配空间的固有缺陷,即在栈满或者其他需要重新调整存储空间时需要移动大量元素。为此,栈可以采用链式存储方式来实现。在 Python 中我们通过构造链表节点 $Node$ 的方式来实现。这种采用链式存储结构的栈也被称为 **「链式栈」**。 |
116 | 116 |
|
117 |
| - |
| 117 | + |
118 | 118 |
|
119 |
| -#### 2.3.1 堆栈的链式存储基本描述 |
| 119 | +#### 2.3.1 栈的链式存储基本描述 |
120 | 120 |
|
121 | 121 | 我们约定 $self.top$ 指向栈顶元素所在位置。
|
122 | 122 |
|
123 | 123 | - **初始化空栈**:使用列表创建一个空栈,并令栈顶元素指针 $self.top$ 指向 $None$,即 $self.top = None$。
|
124 |
| -- **判断栈是否为空**:当 $self.top == None$ 时,说明堆栈为空,返回 $True$,否则返回 $False$。 |
| 124 | +- **判断栈是否为空**:当 $self.top == None$ 时,说明栈为空,返回 $True$,否则返回 $False$。 |
125 | 125 | - **插入元素(进栈、入栈)**:创建值为 $value$ 的链表节点,插入到链表头节点之前,并令栈顶指针 $self.top$ 指向新的头节点。
|
126 |
| -- **删除元素(出栈、退栈)**:先判断堆栈是否为空,为空直接抛出异常。如果堆栈不为空,则先使用变量 $cur$ 存储当前栈顶指针 $self.top$ 指向的头节点,然后令 $self.top$ 沿着链表移动 $1$ 位,然后再删除之前保存的 $cur$ 节点。 |
127 |
| -- **获取栈顶元素**:先判断堆栈是否为空,为空直接抛出异常。不为空则返回 $self.top$ 指向的栈顶节点的值,即 $self.top.value$。 |
| 126 | +- **删除元素(出栈、退栈)**:先判断栈是否为空,为空直接抛出异常。如果栈不为空,则先使用变量 $cur$ 存储当前栈顶指针 $self.top$ 指向的头节点,然后令 $self.top$ 沿着链表移动 $1$ 位,然后再删除之前保存的 $cur$ 节点。 |
| 127 | +- **获取栈顶元素**:先判断栈是否为空,为空直接抛出异常。不为空则返回 $self.top$ 指向的栈顶节点的值,即 $self.top.value$。 |
128 | 128 |
|
129 |
| -#### 2.3.2 堆栈的链式存储实现代码 |
| 129 | +#### 2.3.2 栈的链式存储实现代码 |
130 | 130 |
|
131 | 131 | ```python
|
132 | 132 | class Node:
|
@@ -166,13 +166,13 @@ class Stack:
|
166 | 166 | return self.top.value
|
167 | 167 | ```
|
168 | 168 |
|
169 |
| -## 3. 堆栈的应用 |
| 169 | +## 3. 栈的应用 |
170 | 170 |
|
171 |
| -堆栈是算法和程序中最常用的辅助结构,其的应用十分广泛。堆栈基本应用于两个方面: |
| 171 | +栈是算法和程序中最常用的辅助结构,其的应用十分广泛。栈基本应用于两个方面: |
172 | 172 |
|
173 |
| -- 使用堆栈可以很方便的保存和取用信息,因此长被用作算法和程序中的辅助存储结构,临时保存信息,供后面操作中使用。 |
| 173 | +- 使用栈可以很方便的保存和取用信息,因此长被用作算法和程序中的辅助存储结构,临时保存信息,供后面操作中使用。 |
174 | 174 | - 例如:操作系统中的函数调用栈,浏览器中的前进、后退功能。
|
175 |
| -- 堆栈的后进先出规则,可以保证特定的存取顺序。 |
| 175 | +- 栈的后进先出规则,可以保证特定的存取顺序。 |
176 | 176 | - 例如:翻转一组元素的顺序、铁路列车车辆调度。
|
177 | 177 |
|
178 | 178 | 下面我们来讲解一下栈应用的典型例子。
|
@@ -350,7 +350,7 @@ class Solution:
|
350 | 350 |
|
351 | 351 | ## 练习题目
|
352 | 352 |
|
353 |
| -- [堆栈基础题目列表](https://github.com/ITCharge/AlgoNote/tree/main/docs/00_preface/00_06_categories_list.md#%E5%A0%86%E6%A0%88%E5%9F%BA%E7%A1%80%E9%A2%98%E7%9B%AE) |
| 353 | +- [栈基础题目列表](https://github.com/itcharge/AlgoNote/tree/main/docs/00_preface/00_06_categories_list.md#%E6%A0%88%E5%9F%BA%E7%A1%80%E9%A2%98%E7%9B%AE) |
354 | 354 |
|
355 | 355 | ## 参考资料
|
356 | 356 |
|
|
0 commit comments