# Stack 概念: `Stack` 是 C# 提供的一个==非泛型栈集合== 栈的特点是:==先进后出,后进先出== 英文: `LIFO`:Last In First Out 简单理解: 像一摞盘子 最后放上去的,最先被拿走 命名空间: ```csharp using System.Collections; ``` ---- # 通常用法 1. 处理需要“后进先出”的数据 2. 临时保存操作记录 3. 实现撤销、回退、调用顺序等逻辑 4. 学习栈这种数据结构 实际开发中: 新代码更推荐使用 `Stack` 这里的 `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` ---- # 一句话记忆 ==Stack 是后进先出的集合,最后放进去的最先出来。== ---- # 面试/复习时怎么说 可以这样答: “Stack 是栈结构,特点是后进先出,也就是 LIFO。 常用方法有 `Push`、`Pop` 和 `Peek`,分别表示入栈、出栈、查看栈顶。 非泛型 Stack 存的是 object,取值时可能需要强制类型转换,新项目中更推荐使用 `Stack`。” ---- 引用: 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 #栈 #集合 #进阶