C#利用栈实现加减乘除运算

yizhihongxing

C#利用栈实现加减乘除运算攻略

背景

在程序设计中,实现加减乘除运算是非常基础和常见的需求。而在计算表达式时,我们可以利用栈的特性来进行运算,这样可以避免使用递归等复杂的算法。本篇文章将介绍如何使用C#语言利用栈实现加减乘除运算。

方案

1.利用栈实现加减运算

我们可以使用两个栈numStackopStack,分别存放数字和操作符。具体的方法如下:

1.1. 遍历待计算的字符串,依次处理每一个字符。
1.2. 如果遇到数字,将其入数字栈numStack
1.3. 如果遇到操作符,分两种情况处理:
1.3.1. 如果操作符栈opStack为空,则将操作符直接入栈。
1.3.2. 如果操作符不为空,比较当前操作符和操作符栈顶的优先级。如果当前操作符优先级不高于栈顶操作符,则从数字栈numStack中取出两个数进行运算,并将结果入栈numStack,重复此过程直到当前操作符优先级高于栈顶操作符或操作符栈为空,最后将当前操作符入栈opStack
1.4.字符遍历结束后,如果操作符栈不为空,则依次取出操作符和数字进行运算。

下面是使用上述算法计算表达式(4+2)*5-3的演示(代码中用#表示空栈):

numStack:   # 4  6  6  6  5  2  30  30  27
opStack:    # +  #  *  -  *  +   #   #   #

具体实现可以参考以下代码示例:

public static double Eval(string expr)
{
    var numStack = new Stack<double>();
    var opStack = new Stack<char>();
    for (int i = 0; i < expr.Length; i++)
    {
        if (char.IsDigit(expr[i]))
        {
            // 提取数字
            int j = i + 1;
            while (j < expr.Length && (char.IsDigit(expr[j]) || expr[j] == '.')) j++;
            numStack.Push(double.Parse(expr.Substring(i, j - i)));
            i = j - 1;
        }
        else
        {
            // 提取操作符
            char op = expr[i];
            while (opStack.Count > 0 && Priority(op) <= Priority(opStack.Peek()))
                numStack.Push(Compute(opStack.Pop(), numStack.Pop(), numStack.Pop()));
            opStack.Push(op);
        }
    }
    while (opStack.Count > 0)
        numStack.Push(Compute(opStack.Pop(), numStack.Pop(), numStack.Pop()));
    return numStack.Pop();
}

private static double Compute(char op, double a, double b)
{
    switch (op)
    {
        case '+': return b + a;
        case '-': return b - a;
        case '*': return b * a;
        case '/': return b / a;
        default: throw new ArgumentException($"Invalid operator \"{op}\".");
    }
}

private static int Priority(char op)
{
    switch (op)
    {
        case '+':
        case '-': return 1;
        case '*':
        case '/': return 2;
        default: throw new ArgumentException($"Invalid operator \"{op}\".");
    }
}

1.2. 利用栈实现加减乘除运算

在进行加减运算时,我们已经使用了栈来处理。接下来我们将介绍如何利用栈实现乘除运算的处理。具体的方法如下:

1.2.1. 遍历待计算的字符串,依次处理每一个字符。
1.2.2. 如果遇到数字,将其入数字栈numStack
1.2.3. 如果遇到乘或除操作符,取出数字栈numStack的栈顶元素a,并再次取出数字栈numStack的栈顶元素b,计算ba的乘(或除)积,并将结果压入数字栈numStack
1.2.4. 如果遇到加或减操作符,则先将其入操作符栈opStack

下面是使用上述算法计算表达式(4+2)*5/3的演示(代码中用#表示空栈):

numStack:   # 4  6 30  10  3.33333333333333
opStack:    # +  #  *   /   #

具体实现可以参考以下代码示例:

public static double Eval(string expr)
{
    var numStack = new Stack<double>();
    var opStack = new Stack<char>();
    for (int i = 0; i < expr.Length; i++)
    {
        if (char.IsDigit(expr[i]))
        {
            // 提取数字
            int j = i + 1;
            while (j < expr.Length && (char.IsDigit(expr[j]) || expr[j] == '.')) j++;
            numStack.Push(double.Parse(expr.Substring(i, j - i)));
            i = j - 1;
        }
        else if (expr[i] == '*' || expr[i] == '/')
        {
            // 计算乘(或除)积
            double a = numStack.Pop();
            double b = numStack.Pop();
            numStack.Push(Compute(expr[i], a, b));
        }
        else if (expr[i] == '+' || expr[i] == '-')
        {
            // 入操作符栈
            opStack.Push(expr[i]);
        }
    }
    while (opStack.Count > 0)
    {
        char op = opStack.Pop();
        double a = numStack.Pop();
        double b = numStack.Pop();
        numStack.Push(Compute(op, a, b));
    }
    return numStack.Pop();
}

private static double Compute(char op, double a, double b)
{
    switch (op)
    {
        case '+': return b + a;
        case '-': return b - a;
        case '*': return b * a;
        case '/': return b / a;
        default: throw new ArgumentException($"Invalid operator \"{op}\".");
    }
}

结论

利用栈实现加减乘除运算,不仅比递归等算法容易理解,而且还可以避免出现栈溢出等问题,因此在程序设计中非常实用。本篇文章给出了两种实现方法,读者可以根据实际需求选择适合的方法。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C#利用栈实现加减乘除运算 - Python技术站

(0)
上一篇 2023年5月31日
下一篇 2023年5月31日

相关文章

  • C# Add(T):将元素添加到 ICollection

    C#中的Add(T)方法主要是用来向List集合中添加元素的,T代表数据类型,可以是整型、浮点型、字符串、对象等等。本文将详细讲解C# Add(T)方法的使用方法和注意点。 语法 以下是Add(T)方法的基本语法: public void Add(T item); 参数 Add(T)方法的参数是要添加到List集合中的元素。 返回值 Add(T)方法没有返回…

    C# 2023年4月19日
    00
  • asp.net neatUpload 支持大文件上传组件

    ASP.NET NeatUpload是一个用于实现大文件上传的组件,它支持各种文件上传场景,并提供了丰富的API以适应不同的需求。下面将详细讲解如何使用该组件实现大文件上传的完整攻略。 1. 安装和配置 首先需要将NeatUpload组件添加到项目中。可使用NuGet安装或者手动下载添加。 Nuget安装: Install-Package NeatUploa…

    C# 2023年6月1日
    00
  • 深入分析C# Task

    深入分析C# Task攻略 什么是C# Task? C# Task是一种异步编程模型,用于执行长时间运行的计算或I/O操作。Task API提供了执行和计划多个异步操作的方法,例如等待任务完成、等待任意完成,或等待任意取消。Task API是.NET Framework 4.5版本中Task Parallel Library (TPL)的一部分。 如何使用T…

    C# 2023年5月15日
    00
  • asp.net 数字签名实例代码

    为了实现数字签名,我们需要使用ASP.NET自带的RSACryptoServiceProvider类。该类可以生成密钥对,对消息进行数字签名,以及验证数字签名。下面是实现数字签名的详细步骤: 步骤一:生成密钥对 首先,我们需要生成一个RSA密钥对,用于数字签名。我们可以使用以下代码生成密钥对: // 创建一个RSA实例 using (var rsa = ne…

    C# 2023年5月31日
    00
  • C# 操作Windows注册表的实现方法

    下面是详细讲解“C# 操作Windows注册表的实现方法”的完整攻略: 介绍 Windows注册表是Windows操作系统的一个基本部分,它是一个分层的数据库,存储着所有的系统和应用程序的配置信息。在C#程序中,我们可以使用Microsoft.Win32命名空间来访问Windows注册表,并进行读、写、删除等操作。 读取注册表项信息 在C#程序中,我们可以使…

    C# 2023年6月7日
    00
  • C#自定义集合初始化器

    C#中的自定义集合初始化器是一种语法糖,它可以让我们更方便地初始化一个自定义集合。下面是一个使用自定义集合初始化器的例子: var list = new MyList<int> { 1, 2, 3 }; 在这个例子中,我们使用了自定义集合初始化器来初始化一个名为MyList的自定义集合,其中包含了3个整数值。 为了使用自定义集合初始化器,我们需要…

    C# 2023年6月7日
    00
  • asp实现WEB打印代码大全

    本文将详细讲解如何使用ASP实现WEB打印,并提供代码示例。本文涉及ASP代码编写与调试的知识,假设读者已经具备一定的ASP编程经验。 准备工作 在开始之前,需要安装好IIS服务器,以便能够调用ASP程序。同时,我们还需要准备好以下工具: Web浏览器:用于访问我们的ASP程序; 文本编辑器:用于编写ASP代码; 打印机:用于打印文档。 实现步骤 第一步:创…

    C# 2023年5月31日
    00
  • C# WPF数据绑定方法以及重写数据模板后数据绑定

    写在前面 本文将会介绍WPF如何实现前后端数据绑定和在进行数据绑定时常用的方法和类以及对于DataGrid、ListView这样的控件重写数据模板后控件如何进行数据绑定。 本文主要针对于数据绑定的基础实现进行介绍,通过此博文你将会有能力编写一个MVVM设计模式的C#、WPF项目。如果您是C#及WPF的资深开发人员本文可能对您没有太大的帮助,但如果你是一个正在…

    C# 2023年4月17日
    00
合作推广
合作推广
分享本页
返回顶部