274 lines
4.9 KiB
Markdown
274 lines
4.9 KiB
Markdown
|
|
# Stack
|
|||
|
|
概念:
|
|||
|
|
`Stack` 是 C# 提供的一个==非泛型栈集合==
|
|||
|
|
栈的特点是:==先进后出,后进先出==
|
|||
|
|
|
|||
|
|
英文:
|
|||
|
|
`LIFO`:Last In First Out
|
|||
|
|
|
|||
|
|
简单理解:
|
|||
|
|
像一摞盘子
|
|||
|
|
最后放上去的,最先被拿走
|
|||
|
|
|
|||
|
|
命名空间:
|
|||
|
|
```csharp
|
|||
|
|
using System.Collections;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
----
|
|||
|
|
# 通常用法
|
|||
|
|
1. 处理需要“后进先出”的数据
|
|||
|
|
2. 临时保存操作记录
|
|||
|
|
3. 实现撤销、回退、调用顺序等逻辑
|
|||
|
|
4. 学习栈这种数据结构
|
|||
|
|
|
|||
|
|
实际开发中:
|
|||
|
|
新代码更推荐使用 `Stack<T>`
|
|||
|
|
这里的 `Stack` 是非泛型版本,主要用于理解集合和数据结构
|
|||
|
|
|
|||
|
|
----
|
|||
|
|
# 语法
|
|||
|
|
创建:
|
|||
|
|
```csharp
|
|||
|
|
Stack stack = new Stack();
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
入栈:
|
|||
|
|
```csharp
|
|||
|
|
stack.Push(数据);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
出栈:
|
|||
|
|
```csharp
|
|||
|
|
object value = stack.Pop();
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
查看栈顶:
|
|||
|
|
```csharp
|
|||
|
|
object value = stack.Peek();
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
数量:
|
|||
|
|
```csharp
|
|||
|
|
stack.Count
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
----
|
|||
|
|
# 基础案例
|
|||
|
|
```csharp
|
|||
|
|
using System;
|
|||
|
|
using System.Collections;
|
|||
|
|
|
|||
|
|
Stack stack = new Stack();
|
|||
|
|
|
|||
|
|
stack.Push("第一步");
|
|||
|
|
stack.Push("第二步");
|
|||
|
|
stack.Push("第三步");
|
|||
|
|
|
|||
|
|
Console.WriteLine(stack.Pop());
|
|||
|
|
Console.WriteLine(stack.Pop());
|
|||
|
|
Console.WriteLine(stack.Pop());
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
输出:
|
|||
|
|
```text
|
|||
|
|
第三步
|
|||
|
|
第二步
|
|||
|
|
第一步
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
理解:
|
|||
|
|
1. `"第一步"` 最先进栈
|
|||
|
|
2. `"第三步"` 最后进栈
|
|||
|
|
3. `Pop()` 会先取出最后进去的元素
|
|||
|
|
|
|||
|
|
----
|
|||
|
|
# Push、Pop、Peek
|
|||
|
|
`Push`:
|
|||
|
|
把元素放到栈顶
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
stack.Push("A");
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
`Pop`:
|
|||
|
|
取出并删除栈顶元素
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
object item = stack.Pop();
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
`Peek`:
|
|||
|
|
只查看栈顶元素,不删除
|
|||
|
|
|
|||
|
|
```csharp
|
|||
|
|
object item = stack.Peek();
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
案例:
|
|||
|
|
```csharp
|
|||
|
|
Stack stack = new Stack();
|
|||
|
|
stack.Push("A");
|
|||
|
|
stack.Push("B");
|
|||
|
|
|
|||
|
|
Console.WriteLine(stack.Peek()); // B
|
|||
|
|
Console.WriteLine(stack.Count); // 2
|
|||
|
|
|
|||
|
|
Console.WriteLine(stack.Pop()); // B
|
|||
|
|
Console.WriteLine(stack.Count); // 1
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
----
|
|||
|
|
# 遍历
|
|||
|
|
```csharp
|
|||
|
|
Stack stack = new Stack();
|
|||
|
|
|
|||
|
|
stack.Push("A");
|
|||
|
|
stack.Push("B");
|
|||
|
|
stack.Push("C");
|
|||
|
|
|
|||
|
|
foreach (object item in stack)
|
|||
|
|
{
|
|||
|
|
Console.WriteLine(item);
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
输出顺序一般是:
|
|||
|
|
```text
|
|||
|
|
C
|
|||
|
|
B
|
|||
|
|
A
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
理解:
|
|||
|
|
遍历 `Stack` 时,也是从栈顶到栈底
|
|||
|
|
|
|||
|
|
----
|
|||
|
|
# 常用成员
|
|||
|
|
```csharp
|
|||
|
|
Stack stack = new Stack();
|
|||
|
|
|
|||
|
|
stack.Push("A");
|
|||
|
|
stack.Push("B");
|
|||
|
|
|
|||
|
|
Console.WriteLine(stack.Count);
|
|||
|
|
Console.WriteLine(stack.Contains("A"));
|
|||
|
|
|
|||
|
|
object top = stack.Peek();
|
|||
|
|
object value = stack.Pop();
|
|||
|
|
|
|||
|
|
stack.Clear();
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
常用方法:
|
|||
|
|
1. `Push(object obj)`:入栈
|
|||
|
|
2. `Pop()`:出栈并删除
|
|||
|
|
3. `Peek()`:查看栈顶但不删除
|
|||
|
|
4. `Contains(object obj)`:判断是否包含
|
|||
|
|
5. `Clear()`:清空
|
|||
|
|
6. `ToArray()`:转成数组
|
|||
|
|
|
|||
|
|
----
|
|||
|
|
# 空栈不能 Pop 或 Peek
|
|||
|
|
错误写法:
|
|||
|
|
```csharp
|
|||
|
|
Stack stack = new Stack();
|
|||
|
|
|
|||
|
|
stack.Pop();
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
原因:
|
|||
|
|
栈里没有元素,不能取栈顶
|
|||
|
|
|
|||
|
|
更稳的写法:
|
|||
|
|
```csharp
|
|||
|
|
if (stack.Count > 0)
|
|||
|
|
{
|
|||
|
|
object value = stack.Pop();
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
`Peek()` 也一样,使用前最好先判断 `Count`。
|
|||
|
|
|
|||
|
|
----
|
|||
|
|
# 取值时要类型转换
|
|||
|
|
```csharp
|
|||
|
|
Stack stack = new Stack();
|
|||
|
|
stack.Push(100);
|
|||
|
|
|
|||
|
|
int num = (int)stack.Pop();
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
原因:
|
|||
|
|
非泛型 `Stack` 中的元素按 `object` 存储
|
|||
|
|
取出来也是 `object`
|
|||
|
|
|
|||
|
|
如果值类型放进去,会涉及装箱和拆箱:
|
|||
|
|
```csharp
|
|||
|
|
stack.Push(100); // 装箱
|
|||
|
|
int num = (int)stack.Pop(); // 拆箱
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
----
|
|||
|
|
# 适合场景:撤销操作
|
|||
|
|
```csharp
|
|||
|
|
Stack undoStack = new Stack();
|
|||
|
|
|
|||
|
|
undoStack.Push("创建角色");
|
|||
|
|
undoStack.Push("移动角色");
|
|||
|
|
undoStack.Push("修改颜色");
|
|||
|
|
|
|||
|
|
if (undoStack.Count > 0)
|
|||
|
|
{
|
|||
|
|
string lastAction = (string)undoStack.Pop();
|
|||
|
|
Console.WriteLine("撤销:" + lastAction);
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
理解:
|
|||
|
|
最后做的操作,通常最先撤销
|
|||
|
|
所以适合用栈
|
|||
|
|
|
|||
|
|
----
|
|||
|
|
# Stack 和 ArrayList 的区别
|
|||
|
|
| 对比点 | ArrayList | Stack |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 访问方式 | 按下标访问 | 只关心栈顶 |
|
|||
|
|
| 数据顺序 | 按添加顺序保存 | 后进先出 |
|
|||
|
|
| 添加方法 | `Add` | `Push` |
|
|||
|
|
| 取出方法 | `list[index]` | `Pop` / `Peek` |
|
|||
|
|
| 适合场景 | 普通列表 | 回退、撤销、临时反向处理 |
|
|||
|
|
|
|||
|
|
----
|
|||
|
|
# 注意
|
|||
|
|
1. `Stack` 在 `System.Collections` 命名空间中
|
|||
|
|
2. `Stack` 是非泛型集合,元素按 `object` 存储
|
|||
|
|
3. 栈的规则是后进先出
|
|||
|
|
4. `Push` 是入栈
|
|||
|
|
5. `Pop` 是取出并删除栈顶
|
|||
|
|
6. `Peek` 是查看栈顶但不删除
|
|||
|
|
7. 空栈调用 `Pop()` 或 `Peek()` 会出错
|
|||
|
|
8. 新项目通常优先使用 `Stack<T>`
|
|||
|
|
|
|||
|
|
----
|
|||
|
|
# 一句话记忆
|
|||
|
|
==Stack 是后进先出的集合,最后放进去的最先出来。==
|
|||
|
|
|
|||
|
|
----
|
|||
|
|
# 面试/复习时怎么说
|
|||
|
|
可以这样答:
|
|||
|
|
|
|||
|
|
“Stack 是栈结构,特点是后进先出,也就是 LIFO。
|
|||
|
|
常用方法有 `Push`、`Pop` 和 `Peek`,分别表示入栈、出栈、查看栈顶。
|
|||
|
|
非泛型 Stack 存的是 object,取值时可能需要强制类型转换,新项目中更推荐使用 `Stack<T>`。”
|
|||
|
|
|
|||
|
|
----
|
|||
|
|
引用:
|
|||
|
|
1. Microsoft Learn: [Stack Class](https://learn.microsoft.com/en-us/dotnet/api/system.collections.stack?view=net-9.0)
|
|||
|
|
2. Microsoft Learn: [System.Collections Namespace](https://learn.microsoft.com/en-us/dotnet/api/system.collections?view=net-9.0)
|
|||
|
|
|
|||
|
|
#Stack
|
|||
|
|
#栈
|
|||
|
|
#集合
|
|||
|
|
#进阶
|