c#实现逆波兰转换与计算

/*
1)遇到操作数,直接输出
2)遇到左括号,进栈
3)遇到右括号,逐个将括号内元素出栈并输出,最后弹出左括号
4)遇到运算符,从栈中弹出元素并输出直到遇到发现更低优先级的元素(或者栈为空)为止,再将遇到的运算符入栈
5)最后栈中所有元素依次弹出并输出
*/

/// <summary>  
/// 逆波兰计算器  
/// </summary>  
static class RPNCalculator  
{  
   /// <summary>  
   /// 逆波兰计算器  
   /// </summary>  
   /// <param name="ls">中缀表达式</param>  
   /// <returns>运算结果</returns>  
    public static double Start(List<string> ls)=>GetValue(Transform(ls));  
    /// <summary>  
    /// 获取运算符优先级  
    /// </summary>  
    /// <param name="str">运算符串</param>  
    /// <returns>优先级</returns>  
    private static int GetPriorLevel(string str)  
    {  
        switch (str\[0\])  
        {  
            case '+':  
            case '-':  
                return 1;  
            case '*':  
            case '/':  
                return 2;  
            case '^':  
                return 3;  
            default:  
                return 0;  
        }  
    }  
    /// <summary>  
    /// 二元运算  
    /// </summary>  
    /// <param name="op">运算符</param>  
    /// <param name="x">第一个数</param>  
    /// <param name="y">第二个树</param>  
    /// <returns>运算结果</returns>  
    private static double Calculate(string op,double x, double y)  
    {  
        switch (op)  
        {  
            case "+":  
                return y+x;  
            case "-":  
                return y-x;  
            case "*":  
                return y*x;  
            case "/":  
                return y/x;  
            case "^":  
                return Math.Pow(y, x);  
            default:  
                return 0;  
        }  
    }  
    /// <summary>  
    /// 是否是数字  
    /// </summary>  
    /// <param name="str">字符串</param>  
    /// <returns>布尔值</returns>  
    private static bool IsNum(string str) => Regex.IsMatch(str, @"^(-?\\d+)(\\.\\d+)?$");  
    /// <summary>  
    /// 逆波兰转换  
    /// </summary>  
    /// <param name="str">中缀表达式</param>  
    /// <returns>逆波兰式</returns>  
    private static List<string> Transform(List<string> ls)  
    {  
#if TEST  
        foreach (var item in ls)  
            Write(item + " ");  
        WriteLine();  
#endif  
        //存放转换结果  
        List<string> ans = new List<string>();  
        //栈  
        SQStack<string> sk = new SQStack<string>();  
        for(int i=0;i<ls.Count;++i)  
        {  
            var item = ls\[i\].Trim();  
            //如果是数字,直接输出  
            if (IsNum(item))  
                ans.Add(item);  
            //如果是"(",进栈  
            else if (item == "(")  
                sk.Push(item);  
            //如果是")",括号内的元素出栈并输出  
            else if (item == ")")  
            {  
                while (sk.GetTop() != "(")  
                    ans.Add(sk.Pop());  
                sk.Pop();//并将"("出栈  
            }  
            //其他运算符的情况  
            else  
            {  
                //栈中弹出元素直到遇到发现更低优先级的元素(或者栈为空)为止  
                while (!sk.IsEmpty() && GetPriorLevel(sk.GetTop()) > GetPriorLevel(item))  
                    ls.Add(sk.Pop());  
                sk.Push(item);//运算符入栈  
            }  
        }  
        //输入末尾,所有元素依次弹出  
        while (!sk.IsEmpty())  
            ans.Add(sk.Pop());  
        return ans;  
    }  
    /// <summary>  
    /// 逆波兰求值  
    /// </summary>  
    /// <param name="ls">逆波兰式</param>  
    /// <returns>运算结果</returns>  
    private static double GetValue(List<string> ls)  
    {  
#if TEST  
        foreach (var item in ls)  
            Write(item + " ");  
        WriteLine();  
#endif  
        SQStack<double> sk = new SQStack<double>();  
        foreach (var item in ls)  
        {  
            //遇到数字就进栈  
            if(IsNum(item))  
                sk.Push(double.Parse(item));  
            else//否则遇到符号,出栈两个数字并运算  
              sk.Push(Calculate(item, sk.Pop(), sk.Pop()));//运算结果进栈  
        }  
        return sk.Pop();  
    }  
}

转载于:https://my.oschina.net/u/3848121/blog/1919776

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
波兰算法同样适用于有括号的表达式。我们可以使用一个栈来处理括号。当我们遇到左括号时,将其压入栈中。当我们遇到右括号时,我们可以从栈中弹出所有操作符,直到遇到左括号为止。最后,我们将所有弹出的操作符应用于操作数。最后,我们将计算结果压入栈中。 以下是一个处理有括号的波兰算法实现的示例代码: ```csharp using System; using System.Collections.Generic; public class Program { public static void Main() { string expression = "2 * (3 + 4)"; Console.WriteLine("Expression: " + expression); Console.WriteLine("Result: " + Evaluate(expression)); } public static double Evaluate(string expression) { Stack<double> stack = new Stack<double>(); Stack<char> operators = new Stack<char>(); foreach (char c in expression) { if (char.IsDigit(c)) { stack.Push(double.Parse(c.ToString())); } else if (c == '(') { operators.Push(c); } else if (c == ')') { while (operators.Peek() != '(') { ApplyOperator(stack, operators.Pop()); } operators.Pop(); // remove the left parenthesis } else if (IsOperator(c)) { while (operators.Count > 0 && Precedence(c) <= Precedence(operators.Peek())) { ApplyOperator(stack, operators.Pop()); } operators.Push(c); } } while (operators.Count > 0) { ApplyOperator(stack, operators.Pop()); } return stack.Pop(); } private static bool IsOperator(char c) { return c == '+' || c == '-' || c == '*' || c == '/'; } private static int Precedence(char c) { switch (c) { case '+': case '-': return 1; case '*': case '/': return 2; default: throw new ArgumentException("Invalid operator: " + c); } } private static void ApplyOperator(Stack<double> stack, char op) { double operand2 = stack.Pop(); double operand1 = stack.Pop(); switch (op) { case '+': stack.Push(operand1 + operand2); break; case '-': stack.Push(operand1 - operand2); break; case '*': stack.Push(operand1 * operand2); break; case '/': stack.Push(operand1 / operand2); break; default: throw new ArgumentException("Invalid operator: " + op); } } } ``` 在上面的代码中,我们使用了两个栈,一个用于存储操作数,另一个用于存储操作符。我们遍历表达式中的每个字符,如果它是一个数字,则将其压入操作数栈中。如果它是一个运算符,则将其压入操作符栈中。如果它是左括号,则将其压入操作符栈中。如果它是右括号,则从操作符栈中弹出所有操作符,直到遇到左括号为止,并将这些操作符应用于操作数。最后,我们返回操作数栈中的唯一元素,这就是表达式的计算结果。 在上面的示例中,我们可以计算 "2 * (3 + 4)" 这个表达式,它的计算结果是 14。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值