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

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#自定义事件监听实现方法

    下面我将详细讲解“C#自定义事件监听实现方法”的完整攻略。 一、什么是自定义事件 在C#中,自定义事件是指开发者可以自主定义事件,而不是使用已经定义好的事件。使用自定义事件可以让代码更灵活,同时也可以让代码更易于维护。 二、自定义事件的实现方法 1. 声明事件委托 在声明自定义事件之前,需要先声明事件委托。事件委托是一种特殊的委托类型,用于封装一个或多个接受…

    C# 2023年6月1日
    00
  • C#实现的图片、string相互转换类分享

    下面是详细讲解“C#实现的图片、string相互转换类分享”的完整攻略: 简述 在C#编程中,我们常常需要将图片转换为字符串或将字符串转换为图片。要实现这一功能,需要一个类来帮助我们完成这一操作。在本文中,我们将分享一个通用的图片与字符串相互转换的类,以供大家参考使用。 实现过程 1. 将图片转换为字符串 步骤 加载图片,使用Bitmap类; 将图片转换为字…

    C# 2023年6月8日
    00
  • ASP.NET MVC使用typeahead.js实现输入智能提示功能

    当我们需要在 ASP.NET MVC 应用程序中实现输入智能提示功能时,可以使用 typeahead.js 插件。typeahead.js 可以根据用户输入的字符,从服务器获取匹配的建议列表,并输入框下方显示这些建议。以下是详细的攻略: 步骤1:装 typeahead.js 在 Visual Studio 中打开项目,键单击项目名称,选择“管理 NuGet …

    C# 2023年5月12日
    00
  • C# 读取ttf字体文件里的Unicode实现

    下面是详细讲解“C# 读取ttf字体文件里的Unicode实现”的完整攻略。 1. 背景知识 在进行C#读取ttf字体文件里的Unicode实现前,需要掌握以下几个背景知识: 什么是ttf字体文件 什么是Unicode编码 C#中的编码相关类 2. 实现方法 2.1 读取ttf字体文件 使用C#读取ttf字体文件可以使用.NET Framework自带的字体…

    C# 2023年5月31日
    00
  • ASP.NET Core 依赖注入框架的使用

    在 ASP.NET Core 中,依赖注入(Dependency Injection,DI)是一种设计模式,它可以帮助我们管理应用程序中的对象和服务。ASP.NET Core 内置了一个依赖注入框架,可以帮助我们轻松地实现依赖注入。以下是 ASP.NET Core 依赖注入框架的完整攻略: 步骤一:注册服务 在 ASP.NET Core 中,可以使用 Con…

    C# 2023年5月17日
    00
  • ASP.NET Core实现AES-GCM加密算法

    ASP.NET Core是一个跨平台的Web应用程序框架,提供了丰富的加密算法库,其中包括AES-GCM加密算法。在本文中,我们将详细讲解如何在ASP.NET Core中实现AES-GCM加密算法,包括环境搭建、代码实现、示例说明等。 环境搭建 在开始实现AES-GCM加密算法之前,我们需要先搭建好ASP.NET Core的开发环境。具体来说,我们需要安装以…

    C# 2023年5月16日
    00
  • 通用的CRUD之LiteDB

    前言 你要开发一个系统,是不是首要任务是先建库,建表,建字段,既所谓的数据建模(听起来高大上一点,数据建模也确实是个烧脑的活),要费不少功夫。不知你是否遇到过这样的场景。A产品有3个测试参数,B产品有6个测试参数,而且值和类型都各不相同,用SQL你要怎么建表呢?有人会说这简单“参数名,参数值两列搞定”,NO!数据类型考虑了吗,数据量考虑了吗?有人又说”每个参…

    C# 2023年5月10日
    00
  • ASP.NET缓存 方法和最佳实践

    当网站面临高并发访问或者数据处理成本太高的时候,ASP.NET缓存就成为了处理这类问题的有效工具。本文将详细讲解ASP.NET缓存的方法和最佳实践,以帮助读者更好的利用ASP.NET缓存提升网站性能。 基础知识 什么是ASP.NET缓存? ASP.NET缓存是一种内存缓存机制,它可以存储和检索各种类型的数据,如数据源、页面输出、分布式应用程序和对象等。使用A…

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