C# 堆栈推送和弹出示例

⚡ 智能摘要

C# 中的栈是 System.Collections 命名空间中的一个集合,它遵循后进先出 (LIFO) 原则,其中 Push 方法将元素添加到栈顶,Pop 方法将其移除。

  • 📚 后进先出原则: 栈的工作原理就像一摞书,最后压入的元素最先被移除。
  • ➕ 推和弹出: Push 方法将一个元素添加到栈顶,而 Pop 方法移除并返回栈顶元素。
  • 👀 偷看、计数、包含: Peek 方法读取顶部元素而不将其删除,而 Count 和 Contains 报告大小和成员。
  • 🧪 示例: 两个控制台程序演示了如何使用 Count 和 Contains 进行 Push 操作,然后再使用 Pop 操作,以便您可以…… trace 后进先出顺序。
  • 🛠️ 通用堆栈: 堆栈System.Collections.Generic 中的类增加了编译时类型安全性,避免了对新 C# 代码进行装箱。
  • 🤖 人工智能辅助: GitHub Copilot 为 C# Stack 操作搭建脚手架,而 ML.NET 通过类型化集合而不是非泛型堆栈读取数据。

C# 堆栈

C# 中的 Stack 是什么?

堆栈是一种特殊情况的集合,代表了后进先出 (LIFO) 的概念。为了首先理解 LIFO,我们举个例子。想象一下一堆书,每本书都叠放在一起。

书籍的“后进先出”概念意味着只能从书堆中取出最上面的书。不能从中间取出一本书,因为那样会扰乱书堆的布局。

因此在 C#,堆栈也以相同的方式工作。元素被添加到堆栈中,一个元素位于另一个元素的顶部。将元素添加到堆栈的过程称为推送操作。要从堆栈中删除元素,也可以删除堆栈最顶部的元素。此操作称为弹出。

让我们更详细地了解 Stack 集合可用的操作。

堆栈的声明

堆栈是借助 Stack 数据类型创建的。关键字“new”用于创建 Stack 对象。然后将该对象分配给变量 st。

Stack st = new Stack()

将元素添加到堆栈

push 方法用于将元素添加到堆栈中。该语句的一般语法如下。

Stack.push(element)

从堆栈中删除元素

pop 方法用于从堆栈中删除元素。pop 操作将返回堆栈的最顶部元素。该语句的一般语法如下。

 Stack.pop()

计数

此属性用于获取 Stack 中的项目数。以下是此语句的一般语法。

Stack.Count

包含

此方法用于查看元素是否存在于 Stack 中。以下是此语句的一般语法。如果元素存在,则该语句将返回 true,否则将返回值 false。

Stack.Contains(element)

现在让我们看看它在代码层面上的运作。下面提到的所有代码都将写入我们的 控制台应用。代码将被写入我们的 Program.cs 文件中。

在下面的程序中,我们将编写代码来了解如何使用上述方法。

示例 1:Stack.Push() 方法

在此示例中,我们将看到

  • 如何创建堆栈。
  • 如何显示堆栈的元素,并使用Count和Contain方法。

C# 中的堆栈

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DemoApplication
{
 class Program
 {
  static void Main(string[] args)
  {
   Stack st = new Stack();
   st.Push(1);
   st.Push(2);
   st.Push(3);

   foreach (Object obj in st)
   {
    Console.WriteLine(obj);
   }
    Console.WriteLine(); Console.WriteLine();
    Console.WriteLine("The number of elements in the stack " +st.Count);
    Console.WriteLine("Does the stack contain the elements 3 "+st.Contains(3));
    Console.ReadKey();
  }
 }
}

Code 解释:-

  1. 第一步是声明堆栈。这里我们将“st”声明为变量,用于保存堆栈的元素。
  2. 接下来,我们向堆栈添加 3 个元素。每个元素都通过 Push 方法添加。
  3. 现在,由于堆栈元素不能通过索引位置访问,就像 数组列表,我们需要使用不同的方法来显示堆栈的元素。对象 (obj) 是一个临时变量,它被声明用于保存堆栈的每个元素。然后我们使用 foreach 语句遍历堆栈的每个元素。对于每个堆栈元素,将值分配给 obj 变量。然后我们使用 Console.Writeline 命令将值显示到控制台。
  4. 我们正在使用 Count 属性(st.count) 获取堆栈中的项目数。此属性将返回一个数字。然后我们将该值显示到控制台。
  5. 然后我们使用 Contains 方法查看堆栈中是否存在值 3。这将返回 true 或 false 值。然后我们将此返回值显示到控制台。

如果正确输入上述代码并运行程序,将显示以下输出。

输出:

C# 中的堆栈

从输出中我们可以看到堆栈的元素被显示了出来。此外,还显示了 True 的值,表示值 3 在堆栈上被定义。

注意::您已经注意到,最后推送到堆栈的元素首先显示。这是堆栈的最顶部元素。堆栈元素的数量也显示在输出中。

示例 2:Stack.Pop() 方法

现在让我们看看“移除”功能。我们将看到从堆栈中删除最顶部元素所需的代码。

C# 中的堆栈

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DemoApplication
{
 class Program
 {
  static void Main(string[] args)
  {
   Stack st = new Stack();
   st.Push(1);
   st.Push(2);
   st.Push(3);
   
   st.Pop();

   foreach (Object obj in st)
   {
    Console.WriteLine(obj);
   }
    Console.ReadKey();
  }
 }
}

Code 解释:-

  1. 这里我们只需发出用于从堆栈中删除元素的 pop 方法。

如果正确输入上述代码并运行程序,将显示以下输出。

输出:

C# 中的堆栈

我们可以看到元素 3 被从堆栈中移除。

C# Stack Peek() 方法

`Push` 和 `Pop` 方法操作的是栈顶元素,但有时你只需要查看栈顶元素而无需将其移除。`Peek` 方法正是为此而设计的。它会返回栈顶元素的值,同时保持集合不变,这在你想在决定弹出下一个元素之前先测试一下它时非常有用。

步骤1) 创建一个栈,并将三个元素压入其中,使值 3 位于栈顶。

步骤2) 调用 Peek 方法读取顶部元素,然后检查 Count 属性以确认没有删除任何元素。

using System;
using System.Collections;

namespace DemoApplication
{
 class Program
 {
  static void Main(string[] args)
  {
   Stack st = new Stack();
   st.Push(1);
   st.Push(2);
   st.Push(3);
   Console.WriteLine(st.Peek());
   Console.WriteLine(st.Count);
   Console.ReadKey();
  }
 }
}

Code 解释:-

  1. 声明了一个名为 st 的栈,并使用 Push 方法将值 1、2 和 3 添加到栈中,因此 3 成为栈顶元素。
  2. Peek 方法返回顶部元素而不将其删除,Count 属性仍然报告堆栈中项目的完整数量。

程序运行时,它会打印出该值。 3 从 Peek 开始,然后是计数 3这证明该元素仍然在栈上。如果栈为空,Peek 会抛出 Invalid 异常。OperationException,因此在调用之前检查 Count 是安全的。

通用堆栈在 C# 中

以上示例使用了来自 System.Collections 的非泛型 Stack 类,该类将每个元素存储为一个对象。现代 C# 代码通常更倾向于使用泛型 Stack 类。这是 System.Collections.Generic 命名空间中的类。它将栈绑定到单个已声明的类型,因此编译器会检查每次 Push 和 Pop 操作,无需进行类型转换或装箱。

通用堆栈的主要优势下面列出。

  • 型式安全: 类型在声明时就已确定,因此只能推送该类型的值,并且错误会在编译时被捕获。
  • 禁止拳击: 像 int 这样的值类型直接存储,这样就避免了非泛型 Stack 所支付的装箱成本。
  • 清洁器读取: Pop 和 Peek 直接返回声明的类型,因此您无需将结果从对象强制转换回来。
using System;
using System.Collections.Generic;

namespace DemoApplication
{
 class Program
 {
  static void Main(string[] args)
  {
   Stack<string> st = new Stack<string>();
   st.Push("Java");
   st.Push("Python");
   Console.WriteLine(st.Pop());
   Console.ReadKey();
  }
 }
}

在这个例子中,栈被声明为 Stack因此,它只接受字符串值。Pop 方法直接返回一个字符串并打印出来。 Python最后一次推送的值。对于任何新项目,通用堆栈是推荐的选择。

C# 中栈和队列的区别

一叠和一个 队列 栈和队列都是控制元素移除顺序的集合,但它们遵循相反的规则。栈是后进先出(LIFO),而队列是先进先出(FIFO)。选择正确的集合可以让其他开发者清楚地理解你的代码意图。

主要区别如下:

  • 订购: 栈先移除最近添加的元素(后进先出),而队列先移除最旧的元素(先进先出)。
  • 方法: 栈使用 Push 和 Pop 来添加元素,而队列使用 Enqueue 来添加元素,使用 Dequeue 来移除元素。
  • 顶层元素访问: 栈通过 Peek 函数读取下一个元素,队列通过从队首开始的 Peek 函数读取下一个元素。
  • 典型用途: 栈适合撤销功能、表达式求值和递归 trac队列适合调度、缓冲和广度优先遍历。

这两种类型都可以以通用堆栈的形式提供。和队列在 System.Collections.Generic 中,因此无论选择哪种方式,都能获得类型安全。

常见问题

对空栈调用 Pop 或 Peek 会抛出无效异常OperationException。请先检查 Count 属性,或者使用通用的 Stack 方法 TryPop 和 TryPeek,当栈中没有元素时,这些方法会返回 false 而不是抛出异常。

Push 和 Pop 操作的时间复杂度均为 O(1),因为它们只访问栈顶元素。当内部数组需要增长时,偶尔的 Push 操作会调整数组大小,但每次操作的平均时间复杂度保持不变。

不。栈只能通过 Peek 和 Pop 方法访问栈顶元素,因此它不像列表那样有索引访问器。要读取栈中的每个元素,需要使用 foreach 循环遍历栈,或者使用 ToArray 方法复制栈。

Clear 方法会一次性移除栈中的所有元素,并将 Count 重置为零。要改为从栈顶逐个移除元素,请循环调用 Pop 方法,直到 Count 为零。

当多个线程同时修改标准 Stack 类时,其写入操作并非线程安全。对于并发访问,请使用 System.Collections.Concurrent 中的 ConcurrentStack,它提供了无需外部锁的原子 TryPush 和 TryPop 方法。

调用 ToArray 方法将栈复制到一个新数组中,并按从上到下的顺序排列。您还可以将栈传递给 List 构造函数来构建一个通用列表,同时保持栈的完整性。ping 相同的顺序。

是的。GitHub Copilot 会根据简短的注释或方法名自动生成栈声明、Push 和 Pop 调用以及 foreach 循环。它通常会建议使用通用的栈版本,因为这是新建 C# 代码的推荐集合。

栈很少用于存储 ML.NET 训练数据,这些数据通常流经类型化集合和 IDataView 管道。然而,LIFO 栈的概念出现在机器学习算法中,用于反向传播。trac国王算法、深度优先搜索以及递归方法调用的管理。

总结一下这篇文章: