Files
2026-06-21 09:51:55 +08:00

274 lines
4.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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
#栈
#集合
#进阶